home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 394_01 / c_sim < prev    next >
Text File  |  1994-01-16  |  73KB  |  3,785 lines

  1. /*C++SIM/
  2.  
  3.  
  4. Department of Computing Science,
  5. The University,
  6. Newcastle upon Tyne,
  7. UK.
  8.  
  9. Permission  to use,  copy,  modify  and distribute   this  program for
  10. evaluation, teaching and/or research purposes only and without  fee is
  11. hereby granted,  providing that this  copyright and  permission notice
  12. appear  on all copies and supporting  documentation,  and that similar
  13. conditions are imposed on any individual  or organization to  whom the
  14. program is distributed. The University of Newcastle upon Tyne makes no
  15. representation about the suitability of this software for any purpose.
  16. It is provided "as is" without express or implied warranty.
  17.  
  18. $Id: Copyright,v 1.1 1993/06/14 13:07:22 nmcl Exp $
  19.  
  20.  
  21. tRandom.cc
  22. TestSet.cc
  23.  
  24. Process.cc
  25.  * Copyright (C) 1993
  26.  *
  27.  * Department of Computing Science,
  28.  * The University,
  29.  * Newcastle upon Tyne,
  30.  * UK.
  31.  */
  32.  
  33.  
  34. #ifndef ELEMENT_H_
  35. #include "Element.h"
  36. #endif
  37.  
  38. #ifndef SET_H_
  39. #include "Set.h"
  40. #endif
  41.  
  42.  
  43. Element::Element ()
  44.                   : value(0)
  45. {
  46. }
  47.  
  48. Element::Element (long x)
  49.                         : value(x)
  50. {
  51. }
  52.  
  53. Element::~Element ()
  54. {
  55. }
  56.  
  57. boolean Element::Belongs (Set* toCheck) const
  58. {
  59.     boolean found = false;
  60.     Element* temp = (Element*) toCheck->First();
  61.     
  62.     while ((temp) && (!found))
  63.     {
  64.     if (temp->GetValue() == value)
  65.         found = true;
  66.     else
  67.         temp = (Element*) temp->Suc();
  68.     }
  69.     
  70.     return found;
  71. }
  72.  
  73.  
  74. #ifdef NO_INLINES
  75. #  define ELEMENT_CC_
  76. #  include "Element.n"
  77. #  undef ELEMENT_CC_
  78. #endif
  79. t.
  80. Process.cc
  81. Process.cc
  82.  * Copyright (C) 1993
  83.  *
  84.  * Department of Computing Science,
  85.  * The University,
  86.  * Newcastle upon Tyne,
  87.  * UK.
  88.  */
  89.  
  90.  
  91. /*
  92.  * This is used to simply test the operation of the Head and Link classes.
  93.  */
  94.  
  95.  
  96. #ifndef ELEMENT_H_
  97. #define ELEMENT_H_
  98.  
  99. #ifndef COMMON_H_
  100. #include "common.h"
  101. #endif
  102.  
  103. #ifndef LINK_H_
  104. #include "Link.h"
  105. #endif
  106.  
  107.  
  108. class Set;
  109.  
  110.  
  111. class Element : public Link
  112. {
  113. public:
  114.     Element ();
  115.     Element (long);
  116.     ~Element ();
  117.     
  118.     boolean Belongs (Set*) const;
  119.  
  120.     long GetValue () const;
  121.     void SetValue (long);
  122.     
  123. private:
  124.     long value;
  125. };
  126.  
  127.  
  128. #include "Element.n"
  129.  
  130. #endif
  131. $
  132. TestSet.cc
  133. Process.cc
  134. Process.cc
  135.  * Copyright (C) 1993
  136.  *
  137.  * Department of Computing Science,
  138.  * The University,
  139.  * Newcastle upon Tyne,
  140.  * UK.
  141.  */
  142.  
  143.  
  144. #if defined(NO_INLINES) && !defined(ELEMENT_CC_)
  145.  
  146. #else
  147.  
  148. #ifndef NO_INLINES
  149. #  define INLINEF inline
  150. #else
  151. #  define INLINEF
  152. #endif
  153.  
  154. INLINEF long Element::GetValue () const
  155. {
  156.     return value;
  157. }
  158.  
  159. INLINEF void Element::SetValue (long x)
  160. {
  161.     value = x;
  162. }
  163.  
  164.  
  165. #ifdef INLINEF
  166. #  undef INLINEF
  167. #endif
  168.  
  169. #endif
  170.  
  171.  * Copyright (C) 1993
  172.  *
  173.  * Department of Computing Science,
  174.  * The University,
  175.  * Newcastle upon Tyne,
  176.  * UK.
  177.  */
  178.  
  179. #ifndef BREAKS_H_
  180. #include "Breaks.h"
  181. #endif
  182.  
  183. #ifndef MACHINE_H_
  184. #include "Machine.h"
  185. #endif
  186.  
  187. #ifndef QUEUE_H_
  188. #include "Queue.h"
  189. #endif
  190.  
  191. extern Machine* M;
  192. extern Queue JobQ;
  193.  
  194. Breaks::Breaks ()
  195. {
  196.     RepairTime = new UniformStream(1, 10);
  197.     OperativeTime = new UniformStream(20, 1000);
  198.     interrupted_service = false;
  199. }
  200.  
  201. Breaks::~Breaks ()
  202. {
  203.     delete RepairTime;
  204.     delete OperativeTime;
  205. }
  206.  
  207. void Breaks::Body ()
  208. {
  209.     for(;;)
  210.     {
  211.     Hold((*OperativeTime)());
  212.     M->Broken();
  213.     M->Cancel();
  214.  
  215.     if(!JobQ.IsEmpty())
  216.         interrupted_service = true;
  217.  
  218.     Hold((*RepairTime)());
  219.     M->Fixed();
  220.     if (interrupted_service)
  221.         M->ActivateAt(M->ServiceTime() + CurrentTime());
  222.     else
  223.         M->ActivateAt();
  224.  
  225.     interrupted_service = false;
  226.     }
  227. }
  228.  
  229. Process.cc
  230.  * Copyright (C) 1993
  231.  *
  232.  * Department of Computing Science,
  233.  * The University,
  234.  * Newcastle upon Tyne,
  235.  * UK.
  236.  */
  237.  
  238. #ifndef BREAKS_H_
  239. #define BREAKS_H_
  240.  
  241. #ifndef RANDOM_H_
  242. #include <Random.h>
  243. #endif
  244.  
  245. #ifndef PROCESS_H_
  246. #include <Process.h>
  247. #endif
  248.  
  249.  
  250. /* Waits for a time interval drawn from the OperativeTime. Then kills of the
  251.  * Machine and waits for a time interval drawn from the RepairTime before
  252.  * restarting the Machine.
  253.  */
  254.  
  255. class Breaks : public Process
  256. {
  257. public:
  258.     Breaks ();
  259.     ~Breaks ();
  260.  
  261.     void Body ();
  262.  
  263. private:
  264.     UniformStream* RepairTime;
  265.     UniformStream* OperativeTime;
  266.     boolean interrupted_service;
  267. };
  268.  
  269. #endif
  270. errupted_service = true;
  271.  
  272.     Hold((*RepairTime)());
  273.     M->Fixed();
  274.     if (interrupted_service)
  275.         M->ActivateAt(M->ServiceTime() + CurrentTime());
  276.     else
  277.         M->ActivateAt();
  278.  
  279.     interrupted_service = false;
  280.     }
  281. }
  282.  
  283. Process.cc
  284.  * Copyright (C) 1993
  285.  *
  286.  * Department of Computing Science,
  287.  * The University,
  288.  * Newcastle upon Tyne,
  289.  * UK.
  290.  */
  291.  
  292. #include <iostream.h>
  293.  
  294. #ifndef PROCESS_H_
  295. #include <Process.h>
  296. #endif
  297.  
  298. #ifndef JOB_H_
  299. #include "Job.h"
  300. #endif
  301.  
  302. #ifndef MACHINE_H_
  303. #include "Machine.h"
  304. #endif
  305.  
  306. #ifndef QUEUE_H_
  307. #include "Queue.h"
  308. #endif
  309.  
  310.  
  311. extern Machine* M;
  312. extern Queue JobQ;
  313. extern long TotalJobs;
  314. extern double TotalResponseTime;
  315. extern Scheduler *sc;
  316.  
  317. Job::Job ()
  318. {
  319.     boolean empty;
  320.  
  321.     ResponseTime = 0;
  322.     ArrivalTime = sc->CurrentTime();
  323.     empty = JobQ.IsEmpty();
  324.     JobQ.Enqueue(this);
  325.     TotalJobs++;
  326.  
  327.     if (empty && !M->Processing() && M->IsOperational())
  328.     M->Activate();
  329. }
  330.  
  331. Job::~Job ()
  332. {
  333.     ResponseTime = sc->CurrentTime() - ArrivalTime;
  334.  
  335. #ifdef DEBUG
  336.     cerr << "ArrivalTime is " << ArrivalTime << "\n";
  337.     cerr << "Time now is " << sc->CurrentTime() << "\n";
  338.     cerr << "ResponseTime is " << ResponseTime << "\n";
  339. #endif
  340.  
  341.     TotalResponseTime += ResponseTime;
  342. }
  343.  
  344.  * Copyright (C) 1993
  345.  *
  346.  * Department of Computing Science,
  347.  * The University,
  348.  * Newcastle upon Tyne,
  349.  * UK.
  350.  */
  351.  
  352. #ifndef JOB_H_
  353. #define JOB_H_
  354.  
  355. /* Instances of this class represent the jobs which the Machine attempts
  356.  * to process.
  357.  * If the -DDEBUG option is added to the CFLAGS for the Makefile then useful
  358.  * debugging code will be produced.
  359.  */
  360.  
  361. class Job
  362. {
  363. public:
  364.     Job ();
  365.     ~Job ();
  366.  
  367. private:
  368.     double ArrivalTime;
  369.     double ResponseTime;
  370. };
  371.  
  372. #endif
  373. ;
  374.  
  375.     ResponseTime = 0;
  376.     ArrivalTime C++SIM/Examples/Machine.cc
  377.  * Copyright (C) 1993
  378.  *
  379.  * Department of Computing Science,
  380.  * The University,
  381.  * Newcastle upon Tyne,
  382.  * UK.
  383.  */
  384.  
  385. #ifndef MACHINE_H_
  386. #include "Machine.h"
  387. #endif
  388.  
  389. #ifndef JOB_H_
  390. #include "Job.h"
  391. #endif
  392.  
  393. #ifndef QUEUE_H_
  394. #include "Queue.h"
  395. #endif
  396.  
  397.  
  398. extern long ProcessedJobs;
  399. extern long JobsInQueue;
  400. extern long CheckFreq;
  401. extern double MachineActiveTime;
  402. extern Queue JobQ;
  403.  
  404. Machine::Machine (double mean)
  405. {
  406.     STime = new ExponentialStream(mean);
  407.     operational = true;
  408.     working = false;
  409. }
  410.  
  411. Machine::~Machine () { delete STime; }
  412.  
  413. void Machine::Body ()
  414. {
  415.     double ActiveStart, ActiveEnd;
  416.  
  417.     for (;;)
  418.     {
  419.     working = true;
  420.  
  421.     while (!JobQ.IsEmpty())
  422.     {
  423.         ActiveStart = CurrentTime();
  424.         CheckFreq++;
  425.  
  426.         JobsInQueue += JobQ.QueueSize();
  427.         Job* J = JobQ.Dequeue();
  428.         Hold((*STime)());
  429.  
  430.         ActiveEnd = CurrentTime();
  431.         MachineActiveTime += ActiveEnd - ActiveStart;
  432.         ProcessedJobs++;
  433.         delete J;
  434.     }
  435.  
  436.     working = false;
  437.     Cancel();
  438.     set_evtime(CurrentTime());
  439.     }
  440. }
  441.  
  442. boolean Machine::Processing () { return working; }
  443.  
  444. void Machine::Broken () { operational = false; }
  445.  
  446. void Machine::Fixed ()
  447. {
  448.     operational = true;
  449.     set_evtime(CurrentTime());
  450. }
  451.  
  452. boolean Machine::IsOperational () { return operational; }
  453.  
  454. double Machine::ServiceTime () { return (*STime)(); }
  455.  
  456.  * Copyright (C) 1993
  457.  *
  458.  * Department of Computing Science,
  459.  * The University,
  460.  * Newcastle upon Tyne,
  461.  * UK.
  462.  */
  463.  
  464. #ifndef MACHINE_H_
  465. #define MACHINE_H_
  466.  
  467. #ifndef RANDOM_H_
  468. #include <Random.h>
  469. #endif
  470.  
  471. #ifndef PROCESS_H_
  472. #include <Process.h>
  473. #endif
  474.  
  475.  
  476. /* This is the machine which services job requests. It is prone to simulated
  477.  * failures caused by the Breaks process.
  478.  */
  479.  
  480. class Machine : public Process
  481. {
  482. public:
  483.     Machine (double);
  484.     ~Machine ();
  485.  
  486.     void Body ();
  487.  
  488.     void Broken ();
  489.     void Fixed ();
  490.     boolean IsOperational ();
  491.     boolean Processing ();
  492.     double ServiceTime ();
  493.  
  494. private:
  495.     ExponentialStream* STime;
  496.     boolean operational;
  497.     boolean working;
  498. };
  499.  
  500. #endif
  501. ();
  502.         CheckFreq++;
  503.  
  504.         JobsInQueue += JobQ.QueueSize();
  505.         Job* J = JobQ.Dequeue();
  506.         Hold((*STime)());
  507.  
  508.         ActiveEnd = CurrentTime();
  509.         MachineActiveTime += ActiveEnd - ActiveStart;
  510.         ProcessedJobs++;
  511.         delete J;
  512.     }
  513.  
  514.     working = false;
  515.     Cancel();
  516.     set_evtime(CurrentTime());
  517.     }
  518. }
  519.  
  520. boolean Machine::ProceC++SIM/Examples/MachineShop.cc
  521.  * Copyright (C) 1993
  522.  *
  523.  * Department of Computing Science,
  524.  * The University,
  525.  * Newcastle upon Tyne,
  526.  * UK.
  527.  */
  528.  
  529. #include <iostream.h>
  530.  
  531. #ifndef PROCESS_H_
  532. #include <Process.h>
  533. #endif
  534.  
  535. #ifndef MACHINESHOP_H_
  536. #include "MachineShop.h"
  537. #endif
  538.  
  539. #ifndef ARRIVALS_H_
  540. #include "Arrivals.h"
  541. #endif
  542.  
  543. #ifndef MACHINE_H_
  544. #include "Machine.h"
  545. #endif
  546.  
  547. #ifndef JOB_H_
  548. #include "Job.h"
  549. #endif
  550.  
  551. #ifndef QUEUE_H_
  552. #include "Queue.h"
  553. #endif
  554.  
  555. #ifndef BREAKS_H_
  556. #include "Breaks.h"
  557. #endif
  558.  
  559.  
  560. Scheduler* sc;
  561. Machine* M;
  562. Queue JobQ;
  563. long TotalJobs = 0;
  564. long ProcessedJobs = 0;
  565. long JobsInQueue = 0;
  566. long CheckFreq = 0;
  567. double TotalResponseTime = 0;
  568. double MachineActiveTime = 0;
  569.  
  570. MachineShop::MachineShop () {}
  571.  
  572. MachineShop::~MachineShop () {}
  573.  
  574. void MachineShop::Body ()
  575. {
  576.     sc = new Scheduler();
  577.     Arrivals* A = new Arrivals(10);
  578.     M = new Machine(8);
  579.     Job* J = new Job;
  580.  
  581. #ifdef BREAKS
  582.     Breaks*  B = new Breaks;
  583.     B->Activate();
  584. #endif
  585.  
  586.     A->Activate();
  587.     sc->Resume();
  588.  
  589.     while (ProcessedJobs < 100000)
  590.     Hold(10000);
  591.  
  592.     cerr << "Total number of jobs processed " << TotalJobs << "\n";    
  593.     cerr << "Total response time of " << TotalResponseTime << "\n";
  594.  
  595.     cerr << "Average response time = " << (TotalResponseTime / ProcessedJobs) << "\n";
  596.     cerr << "Probability that machine is busy = " << (MachineActiveTime / CurrentTime()) << "\n";
  597.     cerr << "Average number of jobs present = " << (JobsInQueue / CheckFreq) << "\n";
  598.     sc->Suspend();
  599.     A->Suspend();
  600.  
  601. #ifdef BREAKS
  602.     B->Suspend();
  603. #endif
  604. }
  605.  
  606. void MachineShop::Await ()
  607. {
  608.     Resume();
  609.     Thread::Self()->Suspend();
  610. }
  611.  
  612.  * Copyright (C) 1993
  613.  *
  614.  * Department of Computing Science,
  615.  * The University,
  616.  * Newcastle upon Tyne,
  617.  * UK.
  618.  */
  619.  
  620. #ifndef MACHINESHOP_H_
  621. #define MACHINESHOP_H_
  622.  
  623. #ifndef PROCESS_H_
  624. #include <Process.h>
  625. #endif
  626.  
  627.  
  628. /* This class starts up all of the main processes involved in the simulation.
  629.  * If the -DBREAKS option is added to the CFLAGS for the Makefile then the
  630.  * Breaks process will be created to deactivate of the Machine process at
  631.  * suitable intervals. Otherwise it will not be created and the Machine will
  632.  * operate uninterrupted.
  633.  */
  634.  
  635. class MachineShop : public Process
  636. {
  637. public:
  638.     MachineShop ();
  639.     ~MachineShop ();
  640.  
  641.     void Body ();
  642.     void Await ();
  643. };
  644.  
  645. #endif
  646.  () {}
  647.  
  648. MachineShop::~MachineShop () {}
  649.  
  650. void MachineShop::Body ()
  651. {
  652.     sc = new Scheduler();
  653.     Arrivals* A = new Arrivals(10);
  654.     M = new Machine(8);
  655.     Job* J = new Job;
  656.  
  657. #ifdef BREAKS
  658.     Breaks*  B = new Breaks;
  659.     B->Activate();
  660. #endif
  661.  
  662.     A->Activate();
  663.     sc->Resume();
  664.  
  665.     while (ProcessedJobs < 100000)
  666.     Hold(10000);
  667.  
  668.    C++SIM/Examples/Main.cc
  669.  * Copyright (C) 1993
  670.  *
  671.  * Department of Computing Science,
  672.  * The University,
  673.  * Newcastle upon Tyne,
  674.  * UK.
  675.  */
  676.  
  677. #include <iostream.h>
  678.  
  679. #ifndef COMMON_H_
  680. #include <common.h>
  681. #endif
  682.  
  683. #ifndef PROCESS_H_
  684. #include <Process.h>
  685. #endif
  686.  
  687. #ifndef MACHINESHOP_H_
  688. #include "MachineShop.h"
  689. #endif
  690.  
  691.  
  692. int main()
  693. {
  694.     Thread_Type::Initialize(); // Initialize the threads package.
  695.  
  696.     MachineShop m; // Start up the real main body of the simulation.
  697.     m.Await(); // Suspend main's thread (NOTE: this MUST be done by all applications.)
  698.  
  699.     return 0;
  700. }
  701. */
  702.  
  703. class MachineShop : public Process
  704. {
  705. public:
  706.     MachineShop ();
  707.     ~MachineShop ();
  708.  
  709.     void Body ();
  710.     void Await ();
  711. };
  712.  
  713. #endif
  714.  () {}
  715.  
  716. MachineShop::~MachineShop () {}
  717.  
  718. void MachineShop::Body ()
  719. {
  720.     sc = new Scheduler();
  721.     Arrivals* A = new Arrivals(10);
  722.     M = new Machine(8);
  723.     Job* J = new Job;
  724.  
  725. #ifdef BREAKS
  726.     Breaks*  B = new Breaks;
  727.     B->Activate();
  728. #endif
  729.  
  730.     A->Activate();
  731.     sc->Resume();
  732.  
  733.     while (ProcessedJobs < 100000)
  734.     Hold(10000);
  735.  
  736.    C++SIM/Examples/Queue.cc
  737.  * Copyright (C) 1993
  738.  *
  739.  * Department of Computing Science,
  740.  * The University,
  741.  * Newcastle upon Tyne,
  742.  * UK.
  743.  */
  744.  
  745. #ifndef QUEUE_H_
  746. #include "Queue.h"
  747. #endif
  748.  
  749. Queue::Queue ()
  750. {
  751.     head = 0;
  752.     length = 0;
  753. }
  754.  
  755. Queue::~Queue () { delete head; }
  756.  
  757. boolean Queue::IsEmpty ()
  758. {
  759.     if (head == 0)
  760.     return true;
  761.     else
  762.     return false;
  763. }
  764.  
  765. long Queue::QueueSize () { return length; }
  766.  
  767. Job* Queue::Dequeue ()
  768. {
  769.     if (IsEmpty())
  770.     return 0;
  771.  
  772.     List* ptr = head;
  773.     head = head->next;
  774.  
  775.     length--;
  776.     return ptr->work;
  777. }
  778.  
  779. void Queue::Enqueue (Job* toadd)
  780. {
  781.     List* ptr = head;
  782.  
  783.     if (IsEmpty())
  784.     {
  785.     head = new List;
  786.     ptr = head;
  787.     }
  788.     else
  789.     {
  790.     while (ptr->next != 0)
  791.         ptr = ptr->next;
  792.  
  793.     ptr->next = new List;
  794.     ptr = ptr->next;
  795.     }
  796.  
  797.     ptr->next = 0;
  798.     ptr->work = toadd;
  799.     length++;
  800. }
  801.  
  802.     
  803.    M = new Machine(8);
  804.     Job* J = new Job;
  805.  
  806. #ifdef BREAKS
  807.     Breaks*  B = new Breaks;
  808.     B->Activate();
  809. #endif
  810.  
  811.     A->Activate();
  812.     sc->Resume();
  813.  
  814.     while (ProcessedJobs < 100000)
  815.     Hold(10000);
  816.  
  817.    C++SIM/Examples/Queue.h
  818.  * Copyright (C) 1993
  819.  *
  820.  * Department of Computing Science,
  821.  * The University,
  822.  * Newcastle upon Tyne,
  823.  * UK.
  824.  */
  825.  
  826. #ifndef QUEUE_H_
  827. #define QUEUE_H_
  828.  
  829. #ifndef PROCESS_H_
  830. #include <Process.h>
  831. #endif
  832.  
  833. #ifndef JOB_H_
  834. #include "Job.h"
  835. #endif
  836.  
  837.  
  838. /* This is the queue on which Jobs are placed before they are used. */
  839.  
  840. struct List
  841. {
  842.     Job* work;
  843.     List* next;
  844. };
  845.  
  846. class Queue
  847. {
  848. public:
  849.     Queue ();
  850.     ~Queue ();
  851.  
  852.     boolean IsEmpty ();
  853.     long QueueSize ();
  854.     Job *Dequeue ();
  855.     void Enqueue (Job*);
  856.  
  857. private:
  858.     List* head;
  859.     long length;
  860. };
  861.  
  862. #endif
  863. ist* ptr = head;
  864.  
  865.     if (IsEmpty())
  866.     {
  867.     head = new List;
  868.     ptr = head;
  869.     }
  870.     else
  871.     {
  872.     while (ptr->next != 0)
  873.         ptr = ptr->next;
  874.  
  875.     ptr->next = new List;
  876.     ptr = ptr->next;
  877.     }
  878.  
  879.     ptr->next = 0;
  880.     ptr->work = toadd;
  881.     length++;
  882. }
  883.  
  884.     
  885.    M = new Machine(8);
  886.     Job* J = new Job;
  887.  
  888. #ifdef BREAKS
  889.     Breaks*  B = new Breaks;
  890.     B->Activate();
  891. #endif
  892.  
  893.     A->Activate();
  894.     sc->Resume();
  895.  
  896.     while (ProcessedJobs < 100000)
  897.     Hold(10000);
  898.  
  899.    C++SIM/Examples/README
  900.  * Copyright (C) 1993
  901.  *
  902.  * Department of Computing Science,
  903.  * The University,
  904.  * Newcastle upon Tyne,
  905.  * UK.
  906.  */
  907.  
  908. This director contains an example of a simulation written using the simulation
  909. package. The example is taken from the book by Isi Mitrani (Simulation
  910. Techniques for Discrete Event Systems p22).
  911.  
  912. The simulation is of a service which attempts to execute as many requests for
  913. jobs as possible. The job requests are queued until the service can deal with
  914. them. However, the service is prone to failures, and so jobs started will be
  915. delayed until the service has been reactivated.
  916.  
  917. The classes provided include:
  918.  
  919.     Arrivals - This class controls the rate at which Jobs arrive at
  920.            the service (Machine)
  921.  
  922.     Breaks - This class controls the availability of the Machine by
  923.          "killing" it and restarting it at intervals drawn from
  924.          a Uniform distribution.
  925.  
  926.     Job - This class represents the jobs which the Machine must process.
  927.  
  928.     Machine - This is the Machine on which the service resides. It obtains
  929.           jobs from the job queue for the service and then attempts to
  930.           execute them. The machine can fail and so the response time for
  931.           jobs is not guaranteed to be the same.
  932.  
  933.     MachineShop - This is the main part of the simulation which starts the
  934.               various processes (Scheduler, Arrivals, Machine, Job)
  935.               involved. It also prints out statistics for the response time
  936.               for the jobs.
  937.  
  938.     Queue - This represents the queue which Jobs are placed on prior to being
  939.         used by the Machine (service).
  940.  
  941.     Main - This is the body of the program which initializes the threads package
  942.            prior to the simulation starting.
  943.  
  944.  * Copyright (C) 1993
  945.  *
  946.  * Department of Computing Science,
  947.  * The University,
  948.  * Newcastle upon Tyne,
  949.  * UK.
  950.  */
  951.  
  952. #ifndef ARRIVALS_H_
  953. #define ARRIVALS_H_
  954.  
  955. #ifndef PROCESS_H_
  956. #include <Process.h>
  957. #endif
  958.  
  959. #ifndef RANDOM_H_
  960. #include <Random.h>
  961. #endif
  962.  
  963.  
  964. /* Controls the rate at which Jobs arrive at the Machine */
  965.  
  966. class Arrivals : public Process
  967. {
  968. public:
  969.     Arrivals (double);
  970.     ~Arrivals ();
  971.  
  972.     void Body ();
  973.  
  974. private:
  975.     ExponentialStream* InterArrivalTime;
  976. };
  977.  
  978. #endif
  979. ver, the service is prone to faiC++SIM/Examples/Arrivals.cc
  980.  * Copyright (C) 1993
  981.  *
  982.  * Department of Computing Science,
  983.  * The University,
  984.  * Newcastle upon Tyne,
  985.  * UK.
  986.  */
  987.  
  988. #include <iostream.h>
  989.  
  990. #ifndef ARRIVALS_H_
  991. #include "Arrivals.h"
  992. #endif
  993.  
  994. #ifndef JOB_H_
  995. #include "Job.h"
  996. #endif
  997.  
  998. Arrivals::Arrivals (double mean) { InterArrivalTime = new ExponentialStream(mean); }
  999.  
  1000. Arrivals::~Arrivals () { delete InterArrivalTime; }
  1001.  
  1002. void Arrivals::Body ()
  1003. {
  1004.     for(;;)
  1005.     {
  1006.     Hold((*InterArrivalTime)());
  1007.     Job* work = new Job();
  1008.     }
  1009. }
  1010. dif
  1011. ver, the service is prone to faiC++SIM/Examples/Makefile
  1012.  
  1013. CC  = cc
  1014. C++ = CC3.0.1
  1015. CPP = /lib/cpp
  1016. LEX = lex
  1017.  
  1018. MDEP = /usr/local/Arjuna/bin/makedepend
  1019. STRIPDEPEND = /usr/local/Arjuna/bin/stripdepend
  1020.  
  1021. CFLAGS   = -g
  1022. CPPFLAGS =
  1023. C++FLAGS = -g +w
  1024. LDFLAGS  = -g
  1025. LEXFLAGS =
  1026.  
  1027. MDEPFLAGS =
  1028.  
  1029. LOCAL_CFLAGS   =
  1030. LOCAL_CPPFLAGS = -I/usr/local/Arjuna/include -I.. -I.
  1031.  
  1032. LOCAL_C++FLAGS =
  1033. LOCAL_LDFLAGS  = -L../ -lThreads \
  1034.     -L/usr/lib -lm -llwp
  1035.     
  1036. LOCAL_MDEPFLAGS = -I/usr/local/include/CC
  1037.  
  1038. OBJECTS    = Arrivals.o Breaks.o Job.o Queue.o Machine.o Main.o MachineShop.o
  1039.  
  1040. SOURCES    = Arrivals.cc Breaks.cc Job.cc Queue.cc Machine.cc Main.cc MachineShop.cc
  1041.  
  1042. HEADERS    = Arrivals.h Breaks.h Job.h Queue.h Machine.h MachineShop.h
  1043.  
  1044. all: Main
  1045.  
  1046. Main: $(OBJECTS) $(HEADERS)  ../libThreads.a
  1047.     $(C++) -o Main $(OBJECTS) $(LDFLAGS) $(LOCAL_LDFLAGS)
  1048.  
  1049. Main.o: Main.cc
  1050.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Main.cc
  1051.  
  1052. MachineShop.o: MachineShop.cc
  1053.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) MachineShop.cc
  1054.  
  1055. Arrivals.o: Arrivals.cc
  1056.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Arrivals.cc
  1057.  
  1058. Breaks.o: Breaks.cc
  1059.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Breaks.cc
  1060.  
  1061. Job.o: Job.cc Job.h
  1062.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Job.cc
  1063.  
  1064. Queue.o: Queue.cc Queue.h
  1065.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Queue.cc
  1066.  
  1067. Machine.o: Machine.cc Machine.h
  1068.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Machine.cc
  1069.  
  1070. clean:
  1071.     rm -f *.o
  1072.  
  1073. vclean: clean
  1074.     rm -f Main *~* *.bak
  1075.  
  1076. depend:
  1077.     $(MDEP) $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(MDEPFLAGS) $(LOCAL_MDEPFLAGS) $(SOURCES)
  1078.  
  1079. # DO NOT DELETE THIS LINE -- make depend depends on it.
  1080.  
  1081.  * Copyright (C) 1993
  1082.  *
  1083.  * Department of Computing Science,
  1084.  * The University,
  1085.  * Newcastle upon Tyne,
  1086.  * UK.
  1087.  */
  1088.  
  1089.  
  1090. /*
  1091.  * This class essentially defines the linked list manager used by the SIMSET
  1092.  * class in SIMULA.
  1093.  */
  1094.  
  1095.  
  1096. #ifndef HEAD_H_
  1097. #include "Head.h"
  1098. #endif
  1099.  
  1100. #ifndef LINK_H_
  1101. #include "Link.h"
  1102. #endif
  1103.  
  1104. #include <iostream.h>
  1105.  
  1106.  
  1107. Head::Head ()
  1108.             : first(0),
  1109.           last(0)
  1110. {
  1111. }
  1112.  
  1113. Head::~Head () { Clear(); }
  1114.  
  1115. void Head::AddFirst (Link* element)
  1116. {
  1117.     if (!element)
  1118.     return;
  1119.     
  1120.     if (!first)
  1121.     {
  1122.     if (element->inList)
  1123.         element->Out();
  1124.     
  1125.     first = element;
  1126.     last = element;
  1127.     element->inList = true;
  1128.     }
  1129.     else
  1130.     {
  1131.     first->Precede(element);
  1132.     first = first->Pred();
  1133.     }
  1134. }
  1135.  
  1136. void Head::AddLast (Link* element)
  1137. {
  1138.     if (last)
  1139.     {
  1140.     element->Follow(last);
  1141.     last = element;
  1142.     }
  1143.     else
  1144.     {
  1145.     if (element->inList)
  1146.         element->Out();
  1147.     
  1148.     element->inList = true;
  1149.     first = element;
  1150.     last = element;
  1151.     }
  1152. }
  1153.  
  1154. long Head::Cardinal () const 
  1155. {
  1156.     long numberOfElements = 0;
  1157.     Link *tempPtr = first;
  1158.     
  1159.     while (tempPtr)
  1160.     {
  1161.     numberOfElements++;
  1162.     tempPtr = tempPtr->Suc();
  1163.     }
  1164.     
  1165.     return numberOfElements;
  1166. }
  1167.  
  1168. void Head::Clear ()
  1169. {
  1170.     Link *tempPtr = first, *marker = 0;
  1171.     
  1172.     while (!tempPtr)
  1173.     {
  1174.     marker = tempPtr;
  1175.     tempPtr = tempPtr->Suc();
  1176.     delete marker;
  1177.     }
  1178. }
  1179.  
  1180.  
  1181. #ifdef NO_INLINES
  1182. #  define HEAD_CC_
  1183. #  include "Head.n"
  1184. #  undef HEAD_CC_
  1185. #endif
  1186.  
  1187. hineShop.cc
  1188.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) MachineShop.cc
  1189.  
  1190. Arrivals.o: Arrivals.cc
  1191.     $(C++) -c $(CPPFLAGS) $C++SIM/Head.h
  1192.  * Copyright (C) 1993
  1193.  *
  1194.  * Department of Computing Science,
  1195.  * The University,
  1196.  * Newcastle upon Tyne,
  1197.  * UK.
  1198.  */
  1199.  
  1200.  
  1201. /*
  1202.  * This class essentially defines the linked list manager used by the SIMSET
  1203.  * class in SIMULA.
  1204.  */
  1205.  
  1206.  
  1207. #ifndef HEAD_H_
  1208. #define HEAD_H_
  1209.  
  1210. #ifndef COMMON_H_
  1211. #include "common.h"
  1212. #endif
  1213.  
  1214.  
  1215. class Link;
  1216.  
  1217.  
  1218. class Head
  1219. {
  1220. public:
  1221.     Head ();
  1222.     virtual ~Head ();
  1223.     
  1224.     Link* First () const;
  1225.     Link* Last () const;
  1226.     
  1227.     void AddFirst (Link*);
  1228.     void AddLast (Link*);
  1229.  
  1230.     long Cardinal () const;
  1231.     boolean Empty () const;
  1232.  
  1233.     void Clear ();
  1234.     
  1235. private:
  1236.     Link *first, *last;
  1237. };
  1238.  
  1239.  
  1240. #include "Head.n"
  1241.  
  1242. #endif
  1243. gnu_thread.h
  1244. Process.cc
  1245. #  include "Head.n"
  1246. #  undef HEAD_CC_
  1247. #endif
  1248.  
  1249. hineShop.cc
  1250.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) MachineShop.cc
  1251.  
  1252. Arrivals.o: Arrivals.cc
  1253.     $(C++) -c $(CPPFLAGS) $C++SIM/Head.n
  1254.  * Copyright (C) 1993
  1255.  *
  1256.  * Department of Computing Science,
  1257.  * The University,
  1258.  * Newcastle upon Tyne,
  1259.  * UK.
  1260.  */
  1261.  
  1262.  
  1263. #if defined(NO_INLINES) && !defined(HEAD_CC_)
  1264.  
  1265. #else
  1266.  
  1267. #ifndef NO_INLINES
  1268. #  define INLINEF inline
  1269. #else
  1270. #  define INLINEF
  1271. #endif
  1272.  
  1273. INLINEF Link* Head::First () const
  1274. {
  1275.     return first;
  1276. }
  1277.  
  1278. INLINEF Link* Head::Last () const
  1279. {
  1280.     return last;
  1281. }
  1282.  
  1283. INLINEF boolean Head::Empty () const
  1284. {
  1285.     return (boolean) (Cardinal() == 0);
  1286. }
  1287.  
  1288. #ifdef INLINEF
  1289. #  undef INLINEF
  1290. #endif
  1291.  
  1292. #endif
  1293.  
  1294. t.h
  1295.  * Copyright (C) 1993
  1296.  *
  1297.  * Department of Computing Science,
  1298.  * The University,
  1299.  * Newcastle upon Tyne,
  1300.  * UK.
  1301.  */
  1302.  
  1303. To create the thread library libThreads.a simply type make. If you do not
  1304. possess Sun's lwp package then you will have to create a new class along the
  1305. same lines as the lwp_thread class and link it into the library. Such a class
  1306. has been provided for the GNU threads package, which is also included.
  1307.  
  1308.  * Copyright (C) 1993
  1309.  *
  1310.  * Department of Computing Science,
  1311.  * The University,
  1312.  * Newcastle upon Tyne,
  1313.  * UK.
  1314.  */
  1315.  
  1316.  
  1317. /*
  1318.  * This class defines the elements of the linked lists within SIMSET.
  1319.  */
  1320.  
  1321.  
  1322. #ifndef LINK_H_
  1323. #include "Link.h"
  1324. #endif
  1325.  
  1326. #ifndef HEAD_H_
  1327. #include "Head.h"
  1328. #endif
  1329.  
  1330.  
  1331. Link::Link ()
  1332.             : prev(0),
  1333.           next(0),
  1334.           inList(false)
  1335. {
  1336. }
  1337.  
  1338. Link::~Link () { RemoveElement(); }
  1339.  
  1340. void Link::RemoveElement ()
  1341. {
  1342.     if (prev)
  1343.     prev->next = next;
  1344.  
  1345.     if (next)
  1346.     next->prev = prev;
  1347.  
  1348.     inList = false;
  1349. }
  1350.  
  1351. Link* Link::Out ()
  1352. {
  1353.     RemoveElement();
  1354.     return this;
  1355. }
  1356.  
  1357. void Link::InTo (Head* list)
  1358. {
  1359.     if (list)
  1360.     {
  1361.     list->AddLast(this);
  1362.     return;
  1363.     }
  1364.     
  1365.     (void) Out();
  1366. }
  1367.  
  1368. void Link::Precede (Link* element)
  1369. {
  1370.     if (!element)
  1371.     (void) Out();
  1372.     else
  1373.     if (!element->inList)
  1374.         (void) Out();
  1375.     else
  1376.     {
  1377.         if (inList)
  1378.         (void) Out();
  1379.         
  1380.         element->addBefore(this);
  1381.     }
  1382. }
  1383.  
  1384. void Link::Follow (Link* element)
  1385. {
  1386.     if (!element)
  1387.     (void) Out();
  1388.     else
  1389.     if (!element->inList)
  1390.         (void) Out();
  1391.     else
  1392.     {
  1393.         if (inList)
  1394.         (void) Out();
  1395.         
  1396.         element->addAfter(this);
  1397.     }
  1398. }
  1399.  
  1400. void Link::addAfter (Link* toAdd)
  1401. {
  1402.     toAdd->inList = true;
  1403.     toAdd->prev = this;
  1404.  
  1405.     if (!next)
  1406.     next = toAdd;
  1407.     else
  1408.     {
  1409.     next->prev = toAdd;
  1410.     toAdd->next = next;
  1411.     next = toAdd;
  1412.     }
  1413. }
  1414.  
  1415. void Link::addBefore (Link* toAdd)
  1416. {
  1417.     toAdd->inList = true;
  1418.     toAdd->next = this;
  1419.  
  1420.     if (!prev)
  1421.     prev = toAdd;
  1422.     else
  1423.     {
  1424.     prev->next = toAdd;
  1425.     toAdd->prev = prev;
  1426.     prev = toAdd;
  1427.     }
  1428. }
  1429.  
  1430. void Link::Follow (Head* list)
  1431. {
  1432.     if (list)
  1433.     list->AddFirst(this);
  1434. }
  1435.  
  1436.  
  1437. #ifdef NO_INLINES
  1438. #  define LINK_CC_
  1439. #  include "Link.n"
  1440. #  undef LINK_CC_
  1441. #endif
  1442.  DELETE THIS LINE -- make depend depends on it.
  1443.  
  1444.  * Copyright (C) 1993
  1445.  *
  1446.  * Department of Computing Science,
  1447.  * The University,
  1448.  * Newcastle upon Tyne,
  1449.  * UK.
  1450.  */
  1451.  
  1452.  
  1453. /*
  1454.  * This class defines the elements of the linked lists within SIMSET.
  1455.  */
  1456.  
  1457.  
  1458. #ifndef LINK_H_
  1459. #define LINK_H_
  1460.  
  1461. #ifndef COMMON_H_
  1462. #include "common.h"
  1463. #endif
  1464.  
  1465.  
  1466. class Head;
  1467.  
  1468.  
  1469. class Link
  1470. {
  1471. public:
  1472.     virtual ~Link ();
  1473.     
  1474.     Link* Suc () const;
  1475.     Link* Pred () const;
  1476.  
  1477.     Link* Out ();
  1478.     void InTo (Head*);
  1479.  
  1480.     void Precede (Link*);
  1481.     void Precede (Head*);
  1482.     void Follow (Link*);
  1483.     void Follow (Head*);
  1484.  
  1485.     boolean inList;
  1486.     
  1487. protected:
  1488.     Link ();           // can only derive from this class
  1489.  
  1490. private:
  1491.     void RemoveElement ();
  1492.  
  1493.     void addAfter (Link*);
  1494.     void addBefore (Link*);
  1495.     
  1496.     Link *prev, *next;
  1497. };
  1498.  
  1499.  
  1500. #include "Link.n"
  1501.  
  1502. #endif
  1503. #endif
  1504.  
  1505.  
  1506. class Head;
  1507.  
  1508.  
  1509. class Link
  1510. {
  1511. public:
  1512.     virtual ~Link ();
  1513.     
  1514.     Link* Suc () const;
  1515.     Link* Pred () const;
  1516.  
  1517.     Link* Out ();
  1518.     void InTo (Head*);
  1519.  
  1520.     void Precede (Link*);
  1521.     void Precede (Head*);
  1522.     void Follow (Link*);
  1523.   C++SIM/Link.n
  1524.  * Copyright (C) 1993
  1525.  *
  1526.  * Department of Computing Science,
  1527.  * The University,
  1528.  * Newcastle upon Tyne,
  1529.  * UK.
  1530.  */
  1531.  
  1532.  
  1533. #if defined(NO_INLINES) && !defined(LINK_CC_)
  1534.  
  1535. #else
  1536.  
  1537. #ifndef NO_INLINES
  1538. #  define INLINEF inline
  1539. #else
  1540. #  define INLINEF
  1541. #endif
  1542.  
  1543. INLINEF Link* Link::Pred () const
  1544. {
  1545.     return prev;
  1546. }
  1547.  
  1548. INLINEF Link* Link::Suc () const
  1549. {
  1550.     return next;
  1551. }
  1552.  
  1553. INLINEF void Link::Precede (Head* list)
  1554. {
  1555.     this->InTo(list);
  1556. }
  1557.  
  1558. #ifdef INLINEF
  1559. #  undef INLINEF
  1560. #endif
  1561.  
  1562. #endif
  1563. Makefile
  1564.  * Copyright (C) 1993
  1565.  *
  1566.  * Department of Computing Science,
  1567.  * The University,
  1568.  * Newcastle upon Tyne,
  1569.  * UK.
  1570.  */
  1571.  
  1572. /*
  1573.  * Various useful definitions.
  1574.  */
  1575.  
  1576.  
  1577. #ifndef COMMON_H_
  1578. #define COMMON_H_
  1579.  
  1580. #include <iostream.h>
  1581.  
  1582. // Do not forget to change the Makefile accordingly for the right thread library!
  1583.  
  1584. // Can choose from LWP_Thread or GNU_Thread
  1585.  
  1586. #define Thread_Type LWP_Thread
  1587.  
  1588. // Can choose from LWPTHREAD or GNUTHREAD
  1589.  
  1590. #define LWPTHREAD
  1591.  
  1592. #ifndef true
  1593. typedef int boolean;
  1594. #define true 1
  1595. #define false 0
  1596. #endif
  1597.  
  1598. #endif
  1599.  
  1600. Process.cc
  1601.     (void) Out();
  1602.     else
  1603.     if (!element->inList)
  1604.         (void) Out();
  1605.     else
  1606.     {
  1607.         if (inList)
  1608.         (void) Out();
  1609.         
  1610.         element->addBefore(this);
  1611.     }
  1612. }
  1613.  
  1614. void Link::Follow (Link* element)
  1615. {
  1616.     if (!element)
  1617.     (void) Out();
  1618.     else
  1619.     if (!element->inList)
  1620.         (void) Out();C++SIM/Process.h
  1621.  * Copyright (C) 1993
  1622.  *
  1623.  * Department of Computing Science,
  1624.  * The University,
  1625.  * Newcastle upon Tyne,
  1626.  * UK.
  1627.  */
  1628.  
  1629. #ifndef PROCESS_H_
  1630. #define PROCESS_H_
  1631.  
  1632. #ifndef COMMON_H_
  1633. #include "common.h"
  1634. #endif
  1635.  
  1636. #ifdef GNUTHREAD
  1637. #  ifndef GNU_THREAD_H_
  1638. #    include "gnu_thread.h"
  1639. #  endif
  1640. #else
  1641. #  ifndef LWP_THREAD_H_
  1642. #    include "lwp_thread.h"
  1643. #  endif
  1644. #endif
  1645.  
  1646.  
  1647. /* This is the main class for the simulation package. All objects which are to possess
  1648.  * independent threads of control but which are to be controlled by the simulation
  1649.  * scheduler MUST be derived from the Process class. The Scheduler, which is also an
  1650.  * object which possesses an independent thread and which exists within the simulation
  1651.  * environment, is shown here, but is only derived from the Thread_Type class and not Process
  1652.  * as it is the central controller for the simulation environment and as such runs independently
  1653.  * of everything else.
  1654.  * If debugging is turned on (-DDEBUG added to the CFLAGS for the Makefile) then the scheduler
  1655.  * will print out the current simulation time and other information.
  1656.  *
  1657.  * Thread_Type is a means of "transparently" changing the thread base class implementation
  1658.  * from (at present) lwp_thread to gnu_thread. This should be changed in the file common.h
  1659.  * and the Makefile may need changing to include the right thread library.
  1660.  */
  1661.  
  1662. static double SimulatedTime = 0.0;
  1663.  
  1664.  
  1665. class Scheduler : public Thread_Type
  1666. {
  1667. public:
  1668.     Scheduler ();
  1669.     ~Scheduler ();
  1670.  
  1671.     void Body ();
  1672.     double CurrentTime () const;
  1673.  
  1674. private:
  1675.     double ReActivateTime;
  1676.     Thread* mainthread;
  1677. };
  1678.  
  1679. class Process : public Thread_Type
  1680. {
  1681. public:
  1682.     static const int Never;
  1683.  
  1684.     virtual ~Process ();
  1685.  
  1686.     double Time () const;            // returns the simulated time at which the current process is active
  1687.     static double CurrentTime ();       // returns the current simulation time
  1688.  
  1689.     // There are four ways to activate a process:
  1690.     //   1) before another process, 
  1691.     //   2) after another process, 
  1692.     //   3) at a specified (simulated) time, or 
  1693.     //   4) after a specified (simulated) delay
  1694.  
  1695.     void Activate ();
  1696.     void ActivateBefore (Process &);
  1697.     void ActivateAfter  (Process &);
  1698.     void ActivateAt     (double AtTime = SimulatedTime, boolean prior = false);
  1699.     void ActivateDelay  (double AtTime = SimulatedTime, boolean prior = false);
  1700.  
  1701.     // Similarly, there are four ways to reactivate
  1702.     // Note that if a process is already scheduled, the reactivate
  1703.     // will simply re-schedule the process.
  1704.  
  1705.     void ReActivateBefore (Process &);
  1706.     void ReActivateAfter  (Process &);
  1707.     void ReActivateAt     (double AtTime = SimulatedTime, boolean prior = false);
  1708.     void ReActivateDelay  (double AtTime = SimulatedTime, boolean prior = false);
  1709.     void ReActivate ();
  1710.  
  1711.  
  1712.     void Cancel ();    // cancels next burst of activity, process becomes idle
  1713.     double  evtime () const;    // time at which process is scheduled to be active
  1714.     void set_evtime (double);  // set wakeuptime (used by Scheduler)
  1715.  
  1716.     boolean idle ();    // true if process is not currently scheduled to wake up
  1717.     boolean terminated () const; // returns whether or not the object has been passivated
  1718.  
  1719.     // The pure virtual function, Body, defines the code that executes in the process
  1720.     virtual void Body () = 0;
  1721.  
  1722. protected:
  1723.     Process ();
  1724.     void Hold (double t);// suspend current process for simulated time t
  1725.     void Passivate ();    // suspend current process (i.e., make idle)
  1726.  
  1727. private:
  1728.     double   wakeuptime;
  1729.     boolean  Terminated;
  1730. };
  1731.  
  1732.  
  1733. #include "Process.n"
  1734.  
  1735. #endif // PROCESS_H
  1736.  
  1737.  * Copyright (C) 1993
  1738.  *
  1739.  * Department of Computing Science,
  1740.  * The University,
  1741.  * Newcastle upon Tyne,
  1742.  * UK.
  1743.  */
  1744.  
  1745. #ifndef PROCESSCONS_H_
  1746. #include "ProcessCons.h"
  1747. #endif
  1748.  
  1749.  
  1750. ProcessCons::ProcessCons (Process &p, ProcessCons *n) { Proc = &p; Next = n; }
  1751.  
  1752.  
  1753. #ifdef NO_INLINES
  1754. #  define PROCESSCONS_CC_
  1755. #  include "ProcessCons.n"
  1756. #  undef PROCESSCONS_CC_
  1757. #endif
  1758. Random.cc
  1759. TestSet.cc
  1760.  * Copyright (C) 1993
  1761.  *
  1762.  * Department of Computing Science,
  1763.  * The University,
  1764.  * Newcastle upon Tyne,
  1765.  * UK.
  1766.  */
  1767.  
  1768. #ifndef PROCESSCONS_H_
  1769. #define PROCESSCONS_H_
  1770.  
  1771. #ifndef COMMON_H_
  1772. #include "common.h"
  1773. #endif
  1774.  
  1775. #ifndef PROCESS_H_
  1776. #include "Process.h"
  1777. #endif
  1778.  
  1779.  
  1780. class ProcessCons
  1781. {
  1782. public:
  1783.     ProcessCons (Process &p, ProcessCons *n);
  1784.     Process     *car ();
  1785.     ProcessCons *cdr ();
  1786.     void SetfCdr (ProcessCons *n);
  1787.  
  1788. private:
  1789.     Process *Proc;
  1790.     ProcessCons *Next;
  1791. };
  1792.  
  1793.  
  1794. #include "ProcessCons.n"
  1795.  
  1796. #endif
  1797. <MC++SIM/ProcessCons.n
  1798.  * Copyright (C) 1993
  1799.  *
  1800.  * Department of Computing Science,
  1801.  * The University,
  1802.  * Newcastle upon Tyne,
  1803.  * UK.
  1804.  */
  1805.  
  1806.  
  1807. #if defined(NO_INLINES) && !defined(PROCESSCONS_CC_)
  1808.  
  1809. #else
  1810.  
  1811. #ifndef NO_INLINES
  1812. #  define INLINEF inline
  1813. #else
  1814. #  define INLINEF
  1815. #endif
  1816.  
  1817. INLINEF Process *ProcessCons::car ()
  1818. {
  1819.     return Proc;
  1820. }
  1821.  
  1822. INLINEF ProcessCons *ProcessCons::cdr ()
  1823. {
  1824.     return Next;
  1825. }
  1826.  
  1827. INLINEF void ProcessCons::SetfCdr (ProcessCons *n)
  1828. {
  1829.     Next = n;
  1830. }
  1831.  
  1832.  
  1833. #ifdef INLINEF
  1834. #  undef INLINEF
  1835. #endif
  1836.  
  1837. #endif
  1838.  
  1839.  * Copyright (C) 1993
  1840.  *
  1841.  * Department of Computing Science,
  1842.  * The University,
  1843.  * Newcastle upon Tyne,
  1844.  * UK.
  1845.  */
  1846.  
  1847. #ifndef PROCESSITERATOR_H_
  1848. #include "ProcessIterator.h"
  1849. #endif
  1850.  
  1851.  
  1852. ProcessIterator::ProcessIterator (ProcessList &L) { ptr = L.Head; }
  1853.  
  1854. Process *ProcessIterator::operator ()()
  1855. {
  1856.     if (ptr)
  1857.     {
  1858.     ProcessCons *p = ptr;
  1859.     ptr = ptr->cdr();
  1860.     return p->car();
  1861.     }
  1862.  
  1863.     return 0;
  1864. }
  1865.  
  1866.  * Copyright (C) 1993
  1867.  *
  1868.  * Department of Computing Science,
  1869.  * The University,
  1870.  * Newcastle upon Tyne,
  1871.  * UK.
  1872.  */
  1873.  
  1874. #ifndef PROCESSITERATOR_H_
  1875. #define PROCESSITERATOR_H_
  1876.  
  1877. #ifndef COMMON_H_
  1878. #include "common.h"
  1879. #endif
  1880.  
  1881. #ifndef PROCESS_H_
  1882. #include "Process.h"
  1883. #endif
  1884.  
  1885. #ifndef PROCESSLIST_H_
  1886. #include "ProcessList.h"
  1887. #endif
  1888.  
  1889. #ifndef PROCESSCONS_H_
  1890. #include "ProcessCons.h"
  1891. #endif
  1892.  
  1893.  
  1894. class ProcessIterator
  1895. {
  1896. public:
  1897.     ProcessIterator (class ProcessList &L);
  1898.     Process *operator ()();
  1899.  
  1900. private:
  1901.     ProcessCons *ptr;
  1902. };
  1903.  
  1904. #endif
  1905. ion
  1906.  * environment, is shown here, but is only derived from the Thread_Type class and not Process
  1907.  * as it is the central controller for the simulation environment and as such runs independently
  1908.  * of everything else.
  1909.  * If debugging is turned on (-DDEBUG added to the CFLAGS for the Makefile) then the scheduler
  1910.  * will print oC++SIM/README
  1911.  * Copyright (C) 1993
  1912.  *
  1913.  * Department of Computing Science,
  1914.  * The University,
  1915.  * Newcastle upon Tyne,
  1916.  * UK.
  1917.  */
  1918.  
  1919. D. McCue, M. Little    Computing Laboratory
  1920. 29 November 1991    University of Newcastle upon Tyne, NE1 7RU, England
  1921.  
  1922. This is version 1.0 of C++SIM, a set of c++ class definitions that mimic the
  1923. process-based simulation facilities of SIMULA and the SIMSET routines.  
  1924.  
  1925. The co-routine facility of Simula is implemented by Sun threads.
  1926. Classes are provided for various random number distributions.
  1927.  
  1928. The following classes are defined:
  1929.  
  1930.     Process    - An abstract class that exports the major functions
  1931.           of the Simula class, process.  To use, derive your own
  1932.           class from the class Process.  The pure virtual function,
  1933.           Body, is the "main" procedure of the class.  Note that,
  1934.           like Simula, a process is not scheduled to run when it is
  1935.           created.  It must be explicitly 'activated'.
  1936.  
  1937.     ProcessList    - A list class for processes that (by default) orders
  1938.           the elements by event time.
  1939.  
  1940.     ProcessIterator - An iterator class for ProcessList.
  1941.  
  1942.     ProcessCons - Allows LISP-like list manipulation (car & cdr).
  1943.  
  1944.     Random - A series of classes which provide various random number
  1945.          streams.
  1946.  
  1947.     Element & Head - These classes form the basis of the SIMSET utility.
  1948.  
  1949.     thread - The basic thread class, which defines what operations other
  1950.          threads packages must provide. This is essentially a template
  1951.          which allows other thread packages to be used as long as they
  1952.          provide at least the operations necessary for this class.
  1953.  
  1954.     lwp_thread - This is the Sun threads class.
  1955.  
  1956.     gnu_thread - This is the interface to Gnu's thread package.
  1957.  
  1958.  
  1959.  
  1960. If you find any bugs or make modifications (e.g., ports to other thread
  1961. packages) or port the package to other systems then please let me know
  1962. so I can keep the sources up-to-date for other users.
  1963.  
  1964. Note: if you are interested in using C++SIM with Gnu threads then get in
  1965. touch with me and I will let you know how to go about that.
  1966.  
  1967. Send to: M.C.Little@ac.uk.newcastle
  1968.  
  1969.  
  1970.  
  1971. er a specified (simulated) delay
  1972.  
  1973.     void Activate ();
  1974.     void ActivateBefore (Process &);
  1975.     void ActivateAfter  (Process &);
  1976.     void ActivateAt     (double AtTime = SimulatedTime, boolean prior = false);
  1977.     void ActivateDelay  (double AtTime = SimulatedTime, boolean prior = false);
  1978.  
  1979.     // Similarly, there are four ways to reactivate
  1980.     // Note that if a process is already scheduled, the reactivate
  1981.     // will simply re-schedule the process.
  1982.  
  1983.     void ReActivateBefore (Process &);
  1984.     void ReActiC++SIM/ProcessList.cc
  1985.  * Copyright (C) 1993
  1986.  *
  1987.  * Department of Computing Science,
  1988.  * The University,
  1989.  * Newcastle upon Tyne,
  1990.  * UK.
  1991.  */
  1992.  
  1993. #ifndef PROCESSLIST_H_
  1994. #include "ProcessList.h"
  1995. #endif
  1996.  
  1997.  
  1998. ProcessList::ProcessList () { Head = 0; }
  1999.  
  2000. void ProcessList::Insert (Process &p, boolean prior)
  2001. {
  2002.     // If list is empty, insert at head
  2003.     if (!Head)
  2004.     {
  2005.     Head = new ProcessCons(p, Head);
  2006.     return;
  2007.     }
  2008.  
  2009.     // Try to insert before (if there is anything scheduled later)
  2010.     ProcessIterator iter(*this);
  2011.  
  2012.     for (Process *prev = 0, *q = iter(); q; prev = q, q = iter())
  2013.     {
  2014.     if (prior)
  2015.     {
  2016.         if (q->evtime() >= p.evtime())
  2017.         {
  2018.         (void) InsertBefore(p, *q);
  2019.         return;
  2020.         }
  2021.     }
  2022.     else
  2023.         if (q->evtime() > p.evtime())
  2024.         {
  2025.         (void) InsertBefore(p, *q);
  2026.         return;
  2027.         }
  2028.     }
  2029.  
  2030.     // Got to insert at the end (currently pointed at by 'prev'
  2031.     (void) InsertAfter(p, *prev);
  2032. }
  2033.  
  2034. boolean ProcessList::InsertBefore (Process &ToInsert, Process &Before)
  2035. {
  2036.     for (ProcessCons *prev=0, *p=Head; p; prev=p, p=p->cdr())
  2037.     if (p->car() == &Before) {
  2038.         ProcessCons *newcons = new ProcessCons(ToInsert, p);
  2039.         if (prev)
  2040.         prev->SetfCdr(newcons);
  2041.         else 
  2042.         Head = newcons;
  2043.  
  2044.         return true;
  2045.     }
  2046.     return false;
  2047. }
  2048.  
  2049. boolean ProcessList::InsertAfter (Process &ToInsert, Process &After)
  2050. {
  2051.     for (ProcessCons *p = Head; p; p = p->cdr())
  2052.     if (p->car() == &After) {
  2053.         ProcessCons *newcons = new ProcessCons(ToInsert, p->cdr());
  2054.         p->SetfCdr(newcons);
  2055.         return true;
  2056.     }
  2057.     return false;
  2058. }
  2059.  
  2060. Process *ProcessList::Remove (const Process *element)
  2061. {
  2062.     Process *p = 0;
  2063.  
  2064.     // Take care of boundary condition - empty list
  2065.     if (!Head) return 0;
  2066.  
  2067.     // Change unspecified element to "remove head of list" request
  2068.     if (element == 0)
  2069.     return(Remove(Head->car()));
  2070.  
  2071.     for (ProcessCons *prev = 0, *ptr = Head; ptr; prev = ptr, ptr = ptr->cdr())
  2072.     {
  2073.     if (ptr->car() == element)
  2074.     {
  2075.         ProcessCons *oldcons = ptr;
  2076.         // unlink the cons cell for the element we're removing
  2077.         if (prev)
  2078.         prev->SetfCdr(ptr->cdr());
  2079.         else
  2080.         Head = ptr->cdr();
  2081.         // return the pointer to the process
  2082.         p = ptr->car();
  2083.         // flush the dead cons cell
  2084.         delete oldcons;
  2085.     }
  2086.     }
  2087.  
  2088.     return p;
  2089. }
  2090. oid ActivateAt     (double AtTime = SimulatedTime, boolean prior = false);
  2091.     void ActivateDelay  (double AtTime = SimulatedTime, boolean prior = false);
  2092.  
  2093.     // Similarly, there are four ways to reactivate
  2094.     // Note that if a process is already scheduled, the reactivate
  2095.     // will simply re-schedule the process.
  2096.  
  2097.     void ReActivateBefore (Process &);
  2098.     void ReActiC++SIM/Random.cc
  2099.  * Copyright (C) 1993
  2100.  *
  2101.  * Department of Computing Science,
  2102.  * The University,
  2103.  * Newcastle upon Tyne,
  2104.  * UK.
  2105.  */
  2106.  
  2107. #include <iostream.h>
  2108. #include <math.h>
  2109.  
  2110. #ifndef RANDOM_H_
  2111. #include "Random.h"
  2112. #endif
  2113.  
  2114.  
  2115. RandomStream::RandomStream (long MGSeed, long LCGSeed)
  2116. {
  2117.     // Clean up input parameters
  2118.     if ((MGSeed&1) == 0) MGSeed--;
  2119.     if (MGSeed<0) MGSeed = -MGSeed;
  2120.     if (LCGSeed<0) LCGSeed = -LCGSeed;
  2121.  
  2122.     // Initialise state
  2123.     MSeed = MGSeed;
  2124.     LSeed = LCGSeed;
  2125.  
  2126.     for (int i=0; i< (sizeof(series)/sizeof(double)); i++)
  2127.     series[i] = MGen();
  2128. }
  2129.  
  2130. double RandomStream::MGen ()
  2131. {
  2132.     // A multiplicative generator, courtesy I. Mitrani 1992,
  2133.     // private correspondence
  2134.     // Y[i+1] = Y[i] * 5^5 mod 2^26
  2135.     // period is 2^24, initial seed must be odd
  2136.  
  2137.     const long int two2the26th = 67108864;    // 2**26
  2138.  
  2139.     MSeed = (MSeed * 25) % two2the26th;
  2140.     MSeed = (MSeed * 25) % two2the26th;
  2141.     MSeed = (MSeed * 5) % two2the26th;
  2142.  
  2143.     return (double) MSeed / (double) two2the26th;
  2144. }
  2145.  
  2146. double RandomStream::Uniform () 
  2147. {
  2148.     // A linear congruential generator based on the algorithm from
  2149.     // "Algorithms", R. Sedgewick, Addison-Wesley, Reading MA, 1983.
  2150.     // pp. 36-38.
  2151.     const long m=100000000;
  2152.     const long b=31415821;
  2153.     const long m1=10000;
  2154.  
  2155.     // Do the multiplication in pieces to avoid overflow
  2156.     long    p0 = LSeed%m1,
  2157.         p1 = LSeed/m1,
  2158.         q0 = b%m1,
  2159.         q1 = b/m1;
  2160.  
  2161.     LSeed = (((((p0*q1+p1*q0)%m1)*m1+p0*q0)%m) + 1) % m;
  2162.  
  2163.     // The results of the LC generator are shuffled with
  2164.     // the multiplicative generator as suggested by
  2165.     // Maclaren and Marsaglia (See Knuth Vol2, Seminumerical Algorithms)
  2166.  
  2167.     long choose = LSeed % (sizeof(series)/sizeof(double));
  2168.  
  2169.     double result = series[choose];
  2170.     series[choose] =  MGen();
  2171.  
  2172.     return result;
  2173. }
  2174.  
  2175. double RandomStream::Error ()
  2176. {
  2177.     const long r=100;
  2178.     const long N=100*r;
  2179.     long i, f[r];
  2180.     for (i=0; i<r; i++) f[i]=0;
  2181.     for (i=0; i<N; i++) f[(int) (Uniform()*r)]++;
  2182.     long t=0;
  2183.     for (i=0; i<r; i++) t += f[i]*f[i];
  2184.     double rt = (double) r*t;
  2185.     double rtN = rt / (double) N - (double) N;
  2186.     return 1.0 - (rtN / r);
  2187. }
  2188.  
  2189. UniformStream::UniformStream (double l, double h, int StreamSelect)
  2190. {
  2191.     lo = l;
  2192.     hi = h;
  2193.     range = hi-lo;
  2194.     for (int ss=0; ss<StreamSelect*1000; ss++) (void) Uniform();
  2195. }
  2196.  
  2197. double UniformStream::operator() ()
  2198. {
  2199.     return lo+(range*Uniform());
  2200. }
  2201.     
  2202. Draw::Draw(double p, int StreamSelect) : s(0,1)
  2203. {
  2204.     prob = p;
  2205.     for (int ss=0; ss<StreamSelect*1000; ss++) (void) s();
  2206. }
  2207.  
  2208. boolean Draw::operator() ()
  2209. {
  2210.     double x = s();
  2211.  
  2212.     if (x >= prob)
  2213.     return true;
  2214.     else
  2215.     return false;
  2216. }
  2217.  
  2218. ExponentialStream::ExponentialStream (double m, int StreamSelect)
  2219. {
  2220.     Mean = m;
  2221.     for (int ss=0; ss<StreamSelect*1000; ss++) (void) Uniform();
  2222. }
  2223.  
  2224. double ExponentialStream::operator() ()
  2225. {
  2226.     return -Mean*log(Uniform());
  2227. }
  2228.  
  2229. ErlangStream::ErlangStream (double m, double s, int StreamSelect)
  2230. {
  2231.     Mean = m;
  2232.     StandardDeviation = s;
  2233.  
  2234.     double z = Mean/StandardDeviation;
  2235.     k = (long) (z*z);
  2236.     for (int ss=0; ss<StreamSelect*1000; ss++) (void) Uniform();
  2237. }
  2238.  
  2239. double ErlangStream::operator() ()
  2240. {
  2241.     double z=1.0;
  2242.     for (int i=0; i<k; i++) z*=Uniform();
  2243.     return -(Mean/k)*log(z);
  2244. }
  2245.  
  2246. HyperExponentialStream::HyperExponentialStream (double m, double s, int StreamSelect)
  2247. {
  2248.     Mean = m;
  2249.     StandardDeviation = s;
  2250.     double cv,z;
  2251.     cv=StandardDeviation/Mean;
  2252.     z = cv*cv;
  2253.     p = 0.5*(1.0-sqrt((z-1.0)/(z+1.0)));
  2254.     for (int ss=0; ss<StreamSelect*1000; ss++) (void) Uniform();
  2255. }
  2256.  
  2257. double HyperExponentialStream::operator() ()
  2258. {
  2259.     double z = (Uniform()>p) ? Mean/(1.0-p) : Mean/p;
  2260.     return -0.5*z*log(Uniform());
  2261. }
  2262.  
  2263. NormalStream::NormalStream (double m, double s, int StreamSelect)
  2264. {
  2265.     Mean = m;
  2266.     StandardDeviation = s;
  2267.     z = 0.0;
  2268.     for (int ss=0; ss<StreamSelect*1000; ss++) (void) Uniform();
  2269. }
  2270.  
  2271. double NormalStream::operator() ()
  2272. {
  2273.     // Use the polar method, due to Box, Muller and Marsaglia
  2274.     // Taken from Seminumerical Algorithms, Knuth, Addison-Wesley, p.117
  2275.  
  2276.     double X2;
  2277.  
  2278.     if (z!=0.0) {
  2279.     X2 = z;
  2280.     z = 0.0;
  2281.     } else {
  2282.     double S, v1, v2;
  2283.     do {
  2284.         v1 = 2.0*Uniform()-1.0;
  2285.         v2 = 2.0*Uniform()-1.0;
  2286.         S = v1*v1 + v2*v2;
  2287.     } while (S>=1.0);
  2288.  
  2289.     S = sqrt((-2.0*log(S))/S);
  2290.     X2 = v1*S;
  2291.     z  = v2*S;
  2292.     }
  2293.  
  2294.     return Mean + X2*StandardDeviation;
  2295. }
  2296.  
  2297.  * Copyright (C) 1993
  2298.  *
  2299.  * Department of Computing Science,
  2300.  * The University,
  2301.  * Newcastle upon Tyne,
  2302.  * UK.
  2303.  */
  2304.  
  2305. #ifndef PROCESSLIST_H_
  2306. #define PROCESSLIST_H_
  2307.  
  2308. #ifndef COMMON_H_
  2309. #include "common.h"
  2310. #endif
  2311.  
  2312. #ifndef PROCESS_H_
  2313. #include "Process.h"
  2314. #endif
  2315.  
  2316. #ifndef PROCESSITERATOR_H_
  2317. #include "ProcessIterator.h"
  2318. #endif
  2319.  
  2320. #ifndef PROCESSCONS_H_
  2321. #include "ProcessCons.h"
  2322. #endif
  2323.  
  2324.  
  2325. class ProcessList
  2326. {
  2327. public:
  2328.     ProcessList ();
  2329.     void Insert (Process &, boolean prior=false);
  2330.     boolean InsertBefore (Process &ToInsert, Process &Before);
  2331.     boolean InsertAfter (Process &ToInsert, Process &After);
  2332.     Process *Remove (const Process *p=0);
  2333.  
  2334. private:
  2335.     friend class ProcessIterator;
  2336.     ProcessCons *Head;
  2337. };
  2338.  
  2339. #endif
  2340. eriod is 2^24, initial seed must be odd
  2341.  
  2342.     const long int two2the26th = 67108864;    // 2**26
  2343.  
  2344.     MSeed = (MSeed * 25) % two2the26th;
  2345.     MSeed = (MSeed * 25) % two2the26th;
  2346.     MSeed = (MSeed * 5) % two2the26th;
  2347.  
  2348.     return (double) MSeed / (double) two2the26th;
  2349. }
  2350.  
  2351. double RandomStream::Uniform () 
  2352. {C++SIM/Set.cc
  2353.  * Copyright (C) 1993
  2354.  *
  2355.  * Department of Computing Science,
  2356.  * The University,
  2357.  * Newcastle upon Tyne,
  2358.  * UK.
  2359.  */
  2360.  
  2361. #ifndef SET_H_
  2362. #include "Set.h"
  2363. #endif
  2364.  
  2365. #ifndef ELEMENT_H_
  2366. #include "Element.h"
  2367. #endif
  2368.  
  2369. #include <iostream.h>
  2370.  
  2371.  
  2372. Set::Set () {}
  2373.  
  2374. Set::~Set () {}
  2375.  
  2376. Set* Set::Intersect (Set* toCheck) const
  2377. {
  2378.     Set* tempSet = new Set;
  2379.     Element *E = 0;
  2380.     
  2381.     if (!Empty() && !toCheck->Empty())
  2382.     {
  2383.     E = (Element*) First();
  2384.     
  2385.     while (E)
  2386.     {
  2387.         if (E->Belongs(toCheck))
  2388.         {
  2389.         Element* toAdd = new Element(E->GetValue());
  2390.         toAdd->InTo(tempSet);
  2391.         }
  2392.         
  2393.         E = (Element*) E->Suc();
  2394.     }
  2395.     }
  2396.  
  2397.     return tempSet;
  2398. }
  2399.  Process *p=0);
  2400.  
  2401. private:
  2402.     friend class ProcessIterator;
  2403.     ProcessCons *Head;
  2404. };
  2405.  
  2406. #endif
  2407. eriod is 2^24, initial seed must be odd
  2408.  
  2409.     const long int two2the26th = 67108864;    // 2**26
  2410.  
  2411.     MSeed = (MSeed * 25) % two2the26th;
  2412.     MSeed = (MSeed * 25) % two2the26th;
  2413.     MSeed = (MSeed * 5) % two2the26th;
  2414.  
  2415.     return (double) MSeed / (double) two2the26th;
  2416. }
  2417.  
  2418. double RandomStream::Uniform () 
  2419. {C++SIM/Random.h
  2420.  * Copyright (C) 1993
  2421.  *
  2422.  * Department of Computing Science,
  2423.  * The University,
  2424.  * Newcastle upon Tyne,
  2425.  * UK.
  2426.  */
  2427.  
  2428. #ifndef RANDOM_H_
  2429. #define RANDOM_H_
  2430.  
  2431. #ifndef COMMON_H_
  2432. #include "common.h"
  2433. #endif
  2434.  
  2435.  
  2436. ////////////////////////////////////////////////////////////////////////////////
  2437. //                                                                            //
  2438. //  This file contains the interfaces for five different (pseudo-) random     //
  2439. //  number  generators:                                                       //
  2440. //                                                                            //
  2441. //  1) Uniform -          returns a  number drawn from a uniform distribution //
  2442. //                        with the given lower and upper bounds.              //
  2443. //                        Note: there are two versions of this class, one     //
  2444. //                              returning integers and the other doubles      //
  2445. //                                                                            //
  2446. //  2) Exponential -      returns a number from an exponential distribution   //
  2447. //                        with the given mean                                 //
  2448. //                                                                            //
  2449. //  3) Erlang -           returns a number from an Erlang distribution with   //
  2450. //                        the given mean and standard deviation               //
  2451. //                                                                            //
  2452. //  4) HyperExponential - returns a number from a hyperexpontial distribution //
  2453. //                        with the given mean and standard deviation          //
  2454. //                                                                            //
  2455. //  5) Normal -           returns a number from a normal distribution with    //
  2456. //                        the given mean and standard deviation.              //
  2457. //                                                                            //
  2458. ////////////////////////////////////////////////////////////////////////////////
  2459.  
  2460.  
  2461. ////////////////////////////////////////////////////////////////////////////////
  2462. // The class RandomStream is an abstract base class from which the other      //
  2463. // distribution classes are derived.                                          //
  2464. ////////////////////////////////////////////////////////////////////////////////
  2465. class RandomStream
  2466. {
  2467. public:
  2468.     RandomStream (long MGSeed=772531L, long LCGSeed=1878892440L);
  2469.     virtual double operator() ()=0;
  2470.     double Error ();    // returns a chi-square error measure on the uniform
  2471.             // distribution function
  2472. protected:
  2473.     double Uniform ();
  2474.  
  2475. private:
  2476.     double MGen ();
  2477.     double series[128];
  2478.     long MSeed, LSeed;
  2479. };
  2480.  
  2481. class UniformStream : public RandomStream
  2482. {
  2483. public:
  2484.     UniformStream (double lo, double hi, int StreamSelect=0);
  2485.     virtual double operator() ();
  2486.  
  2487. private:
  2488.     double lo,hi;
  2489.     double range;
  2490. };
  2491.  
  2492. class Draw
  2493. {
  2494. public:
  2495.     Draw (double p, int StreamSelect=0);
  2496.     virtual boolean operator() ();
  2497. private:
  2498.     UniformStream s;
  2499.     double prob;
  2500. };
  2501.  
  2502. class ExponentialStream : public RandomStream
  2503. {
  2504. public:
  2505.     ExponentialStream (double Mean, int StreamSelect=0);
  2506.     virtual double operator() ();
  2507.  
  2508. private:
  2509.     double Mean;
  2510. };
  2511.  
  2512. class ErlangStream : public RandomStream
  2513. {
  2514. public:
  2515.     ErlangStream (double Mean, double StandardDeviation, int StreamSelect=0);
  2516.     virtual double operator() ();
  2517.  
  2518. private:
  2519.     double Mean,StandardDeviation;
  2520.     long k;
  2521. };
  2522.  
  2523. class HyperExponentialStream : public RandomStream
  2524. {
  2525. public:
  2526.     HyperExponentialStream (double Mean, double StandardDeviation, int StreamSelect=0);
  2527.     virtual double operator() ();
  2528.  
  2529. private:
  2530.     double Mean,StandardDeviation;
  2531.     double p;
  2532. };
  2533.  
  2534. class NormalStream : public RandomStream
  2535. {
  2536. public:
  2537.     NormalStream (double Mean, double StandardDeviation, int StreamSelect=0);
  2538.     virtual double operator() ();
  2539.  
  2540. private:
  2541.     double Mean,StandardDeviation;
  2542.     double z;
  2543. };
  2544.  
  2545. #endif // RANDOM_H
  2546.  
  2547. lgorithms, Knuth, Addison-Wesley, p.117
  2548.  
  2549.     double X2;
  2550.  
  2551.     if (z!=0.0) {
  2552.     X2 = z;
  2553.     z = 0.0;
  2554.     } else {
  2555.     double SC++SIM/Set.h
  2556.  * Copyright (C) 1993
  2557.  *
  2558.  * Department of Computing Science,
  2559.  * The University,
  2560.  * Newcastle upon Tyne,
  2561.  * UK.
  2562.  */
  2563.  
  2564. /*
  2565.  * This is used to simply test the operation of the Head and Link classes.
  2566.  */
  2567.  
  2568. #ifndef SET_H_
  2569. #define SET_H_
  2570.  
  2571. #ifndef COMMON_H_
  2572. #include "common.h"
  2573. #endif
  2574.  
  2575. #ifndef HEAD_H_
  2576. #include "Head.h"
  2577. #endif
  2578.  
  2579. #ifndef LINK_H_
  2580. #include "Link.h"
  2581. #endif
  2582.  
  2583.  
  2584. class Set : public Head
  2585. {
  2586. public:
  2587.     Set ();
  2588.     ~Set ();
  2589.     
  2590.     Set* Intersect (Set*) const;
  2591. };
  2592.  
  2593. #endif
  2594.                                         C++SIM/TestRandom.cc
  2595.  * Copyright (C) 1993
  2596.  *
  2597.  * Department of Computing Science,
  2598.  * The University,
  2599.  * Newcastle upon Tyne,
  2600.  * UK.
  2601.  */
  2602.  
  2603. #include <stdlib.h>    // to get getopt
  2604. #include <iostream.h>
  2605. #include "Random.h"
  2606.  
  2607. void Gen(int count, RandomStream *r, const char *title)
  2608. {
  2609.     // Create and initialise buckets for a bar graph
  2610.     int i;
  2611.     int bucket[100];
  2612.     for (i=0; i<100; i++) bucket[i]=0;
  2613.  
  2614.     // generate numbers and update bucket counts
  2615.     for (i=0; i<count; i++) {
  2616.     double result = (*r)();
  2617.     int idx = result < 0.0 ? 0 : (result > 100.0) ? 100 : (int) result;
  2618.     bucket[idx]++;
  2619.     }
  2620.  
  2621.     // output a title followed by the bucket counts
  2622.     cout << endl << '"' << title << '"' << endl;
  2623.     for (i=0; i<100; i++)
  2624.     cout << i << ".0 " << bucket[i] << endl;
  2625.  
  2626. cerr << "Chi-Square error measure: " << r->Error() << endl;
  2627. }
  2628.  
  2629. int main (int argc, char **argv)
  2630. {
  2631.     extern char *optarg;
  2632.     extern int optind;
  2633.     int c;
  2634.     int count=10000;
  2635.     int errflg = 0;
  2636.     int uniform=0, normal=0, exponential=0, hyperexponential=0, erlang=0;
  2637.     int skip=0;
  2638.  
  2639.     while ((c = getopt(argc, argv, "s:c:unxhe")) != -1)
  2640.         switch(c) {
  2641.         case 'c': count = atoi(optarg); break;
  2642.         case 'u': uniform++; break;
  2643.         case 'n': normal++; break;
  2644.         case 'x': exponential++; break;
  2645.         case 'h': hyperexponential++; break;
  2646.         case 'e': erlang++; break;
  2647.         case 's': skip = atoi(optarg); break;
  2648.  
  2649.         case '?':
  2650.         default: errflg++;
  2651.         }
  2652.  
  2653.     // ASSERT: argc-optind == number of arguments remaining
  2654.     //         argv[optind] == first non-flag argument
  2655.  
  2656.     if (errflg || (argc-optind)) {
  2657.         cerr << "usage: " << argv[0] << "[-c <number>][-u][-n][-x][-h][-e]" << endl;
  2658.  
  2659.         cerr << "\t-c 99\t\tgenerate 99 points for each distribution" << endl;
  2660.         cerr << "\t-u\t\toutput a data set for a uniform distribution" << endl;
  2661.         cerr << "\t-n\t\toutput a data set for a normal distribution" << endl;
  2662.         cerr << "\t-x\t\toutput a data set for an exponential distribution" << endl;
  2663.         cerr << "\t-h\t\toutput a data set for a hyperexponential distribution" << endl;
  2664.         cerr << "\t-e\t\toutput a data set for an erlang distribution" << endl;
  2665.         return 2;
  2666.     }
  2667.  
  2668.     // output a normal distribution by default
  2669.     if (!uniform && !normal && !exponential && !hyperexponential && !erlang)
  2670.     normal++;
  2671.  
  2672.     cout << "TitleText: Random Number Distributions" 
  2673.      << " (" << count << " numbers/distribution)" 
  2674.      << endl;
  2675.  
  2676.     for (int q=0; q<skip; q++) delete new UniformStream(0.0, 100.0);
  2677.  
  2678.     if (uniform) Gen (count, new UniformStream (0.0, 100.0), "Uniform");
  2679.     if (normal) Gen (count, new NormalStream (50.0, 15.0), "Normal");
  2680.     if (exponential) Gen (count, new ExponentialStream(50.0), "Exponential");
  2681.     if (hyperexponential) Gen (count, new HyperExponentialStream(50.0, 55.0), "HyperExponential");
  2682.     if (erlang) Gen (count, new ErlangStream(50.0, 15.0), "Erlang");
  2683.  
  2684.     return 0;
  2685. }
  2686. };
  2687.  
  2688. class Draw
  2689. {
  2690. public:
  2691.     Draw (double p, int StreamSelect=0);
  2692.     virtual boolean operator() ();
  2693. private:
  2694.     UniformStream s;
  2695.     douC++SIM/TestSet.cc
  2696.  * Copyright (C) 1993
  2697.  *
  2698.  * Department of Computing Science,
  2699.  * The University,
  2700.  * Newcastle upon Tyne,
  2701.  * UK.
  2702.  */
  2703.  
  2704. #ifndef SET_H_
  2705. #include "Set.h"
  2706. #endif
  2707.  
  2708. #ifndef ELEMENT_H_
  2709. #include "Element.h"
  2710. #endif
  2711.  
  2712. #include <iostream.h>
  2713.  
  2714.  
  2715. int main ()
  2716. {
  2717.     Set S1, S2;
  2718.     Set *S3 = 0;
  2719.     Element* E = 0;
  2720.     
  2721.     for (int i = 0; i < 10; i++)
  2722.     {
  2723.     E = new Element(i);
  2724.     E->InTo(&S1);
  2725.     }
  2726.     
  2727.     for (int j = 8; j < 14; j++)
  2728.     {
  2729.     E = new Element(j);
  2730.     E->InTo(&S2);
  2731.     }
  2732.  
  2733.     S3 = S1.Intersect(&S2);
  2734.     
  2735.     E = (Element*) S3->First();
  2736.     
  2737.     cout << "Intersection is:" << endl;
  2738.     while (E)
  2739.     {
  2740.     cout << "value: " << E->GetValue() << endl;
  2741.     E = (Element*) E->Suc();
  2742.     }
  2743.     
  2744.     return 0;
  2745. }
  2746.  i++)
  2747.     cout << i << ".0 " << bucket[i] << endl;
  2748.  
  2749. cerr << "Chi-Square error measure: " << r->Error() << endl;
  2750. }
  2751.  
  2752. int main (int argc, char **argv)
  2753. {
  2754.     extern char *optarg;
  2755.     extern int optind;
  2756.     int c;
  2757.     int count=10000;
  2758.     int errflg = 0;
  2759.     int uniform=0, normal=0, exponential=0, hyperexponential=0, erlang=0;
  2760.     C++SIM/Makefile
  2761.  
  2762. CC  = cc
  2763. C++ = CC3.0.1
  2764. CPP = /lib/cpp
  2765. LEX = lex
  2766.  
  2767. MDEP = /usr/local/Arjuna/bin/makedepend
  2768. STRIPDEPEND = /usr/local/Arjuna/bin/stripdepend
  2769.  
  2770. CFLAGS   = -g
  2771. CPPFLAGS = 
  2772. C++FLAGS = -g +w
  2773. LDFLAGS  = -g
  2774. LEXFLAGS =
  2775.  
  2776. MDEPFLAGS =
  2777.  
  2778. LOCAL_CFLAGS   =
  2779. LOCAL_CPPFLAGS = 
  2780.  
  2781. LOCAL_C++FLAGS =
  2782. LOCAL_LDFLAGS  = -L/usr/lib -lm -llwp
  2783.  
  2784. LOCAL_MDEPFLAGS = -I/usr/local/include/CC
  2785.  
  2786. LIB    = libThreads.a
  2787.  
  2788. OBJECTS    = Process.o ProcessIterator.o ProcessList.o ProcessCons.o \
  2789.        Link.o Head.o Set.o Element.o \
  2790.        thread.o lwp_thread.o Random.o
  2791.  
  2792. SOURCES    = Process.cc ProcessIterator.cc ProcessList.cc ProcessCons.cc \
  2793.       Link.cc Head.cc Set.cc Element.cc \
  2794.       thread.cc lwp_thread.cc Random.cc
  2795.  
  2796. HEADERS    = ProcessCons.h ProcessIterator.h ProcessList.h common.h \
  2797.       Link.h Head.h Set.h Element.h \
  2798.       thread.h lwp_thread.h Random.h
  2799.  
  2800. INLINES = Element.n Head.n Link.n Process.n ProcessCons.n
  2801.  
  2802. all: $(LIB)
  2803.  
  2804. Process.o: Process.cc Process.h Process.n
  2805.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Process.cc
  2806.  
  2807. ProcessCons.o: ProcessCons.cc ProcessCons.h ProcessCons.n
  2808.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) ProcessCons.cc
  2809.  
  2810. ProcessIterator.o: ProcessIterator.cc ProcessIterator.h
  2811.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) ProcessIterator.cc
  2812.  
  2813. ProcessList.o: ProcessList.cc ProcessList.h
  2814.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) ProcessList.cc
  2815.  
  2816. Link.o: Link.cc Link.h Link.n
  2817.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Link.cc
  2818.  
  2819. Head.o: Head.cc Head.h Head.n
  2820.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Head.cc
  2821.  
  2822. Set.o: Set.cc Set.h
  2823.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Set.cc
  2824.  
  2825. Element.o: Element.cc Element.h Element.n
  2826.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Element.cc
  2827.  
  2828. Random.o: Random.cc Random.h
  2829.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Random.cc
  2830.  
  2831. thread.o: thread.cc thread.h
  2832.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) thread.cc
  2833.  
  2834. lwp_thread.o: lwp_thread.cc lwp_thread.h
  2835.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) lwp_thread.cc
  2836.  
  2837. gnu_thread.o: gnu_thread.cc gnu_thread.h
  2838.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) gnu_thread.cc
  2839.  
  2840. TestRandom: TestRandom.o $(OBJECTS) $(HEADERS) $(INLINES)
  2841.     $(C++) -o TestRandom TestRandom.o $(LIB) $(LDFLAGS) $(LOCAL_LDFLAGS)
  2842.  
  2843. TestRandom.o: TestRandom.cc
  2844.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) TestRandom.cc
  2845.  
  2846. TestSet: TestSet.o $(OBJECTS) $(HEADERS) $(INLINES)
  2847.     $(C++) -o TestSet TestSet.o $(LIB) $(LDFLAGS) $(LOCAL_LDFLAGS)
  2848.  
  2849. TestSet.o: TestSet.cc
  2850.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) TestSet.cc
  2851.  
  2852. $(LIB) : $(OBJECTS)
  2853.     ar rv $@ $?
  2854.     ranlib $(LIB)
  2855.  
  2856. clean:
  2857.     rm -f *.o
  2858.  
  2859. vclean: clean
  2860.     rm -f *~* libThreads.a TestRandom TestSet
  2861. .a
  2862.  
  2863. OBJECTS    = Process.o ProcessIterator.o ProcessList.o ProcessCons.o \
  2864.        Link.o Head.o Set.o Element.o \
  2865.        thread.o lwp_thrC++SIM/gnu_thread.cc
  2866.  * Copyright (C) 1993
  2867.  *
  2868.  * Department of Computing Science,
  2869.  * The University,
  2870.  * Newcastle upon Tyne,
  2871.  * UK.
  2872.  */
  2873.  
  2874. #include <iostream.h>
  2875. #include <sys/types.h>
  2876.  
  2877. #define _INIT_
  2878. #include <gnulwp.h>
  2879.  
  2880. #ifndef GNUTHREAD_H_
  2881. #include "gnu_thread.h"
  2882. #endif
  2883.  
  2884.  
  2885. long GNU_Thread::base_key = 0;
  2886. boolean GNU_Thread::DoWait = true;
  2887. boolean GNU_Thread::SuspendMain = false;
  2888. int GNU_Thread::count = 0;
  2889. const int GNU_Thread::MaxPriority = 7;
  2890.  
  2891.  
  2892. GNU_Thread::GNU_Thread (int prio)
  2893. {
  2894.     to_wait = 0;
  2895.     caddr_t p1;
  2896.  
  2897.     initlp(MaxPriority);
  2898.     p1 = (caddr_t) this;
  2899.     thread_key = base_key++;
  2900.     my_block = creatp(prio, GNU_Thread::Execute, 8000, 0, 0, p1);
  2901. }
  2902.  
  2903. GNU_Thread::~GNU_Thread () {}
  2904.  
  2905. void GNU_Thread::Execute (int dummy1, char** dummy2, GNU_Thread* p1)
  2906. {
  2907.     // Do this to remove compiler warnings.
  2908.     dummy1 = 0;
  2909.     dummy2 = 0;
  2910.  
  2911.     if ((p1->thread_key == 1) && (Self()->Current_Thread() == 0))
  2912.     {
  2913.     signals(p1->to_wait);
  2914.     p1->Body();
  2915.     }
  2916.     else
  2917.     {
  2918.     p1->to_wait = creats(0);
  2919.     p1->Suspend();
  2920.     p1->Body();
  2921.     }
  2922. }
  2923.     
  2924. void GNU_Thread::Suspend ()
  2925. {
  2926.     if ((thread_key == 0) && (Self()->Current_Thread() == 0) && (count < 2))
  2927.     count++;
  2928.  
  2929.     if ((count == 2) && (!SuspendMain))
  2930.     {
  2931.     SuspendMain = true;
  2932.     struct sem* p = creats(0);
  2933.     waits(p);
  2934.     }
  2935.  
  2936.     if ((thread_key == 1) && (Self()->Current_Thread() == 0))
  2937.     {
  2938.     if (DoWait)
  2939.     {
  2940.         DoWait = false;
  2941.         waits(to_wait);
  2942.     }
  2943.     }    
  2944.     else
  2945.     waits(to_wait);
  2946. }
  2947.  
  2948. void GNU_Thread::Resume ()
  2949. {
  2950.     if ((thread_key == 1) && (Self()->Current_Thread() == 0))
  2951.     {
  2952.     readyp(my_block);
  2953.     to_wait = creats(0);
  2954.     Suspend();
  2955.     }
  2956.     else
  2957.         signals(to_wait);
  2958. }
  2959.  
  2960. long GNU_Thread::Current_Thread () const { return thread_key; }
  2961.  
  2962. void GNU_Thread::Initialize () { initlp(1); }
  2963. AGS) $(LOCAL_C++FLAGS) Set.cc
  2964.  
  2965. Element.o: Element.cc Element.h Element.n
  2966.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Element.cc
  2967.  
  2968. Random.o: Random.cc Random.h
  2969.     $(C++) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(C++FLAGS) $(LOCAL_C++FLAGS) Random.cc
  2970.  
  2971. thread.o: thread.cc thread.h
  2972.     $(C++) -c $(CPPFLAGS) $(LOCALC++SIM/gnu_thread.h
  2973.  * Copyright (C) 1993
  2974.  *
  2975.  * Department of Computing Science,
  2976.  * The University,
  2977.  * Newcastle upon Tyne,
  2978.  * UK.
  2979.  */
  2980.  
  2981. #ifndef GNU_THREAD_H_
  2982. #define GNU_THREAD_H_
  2983.  
  2984. #ifndef COMMON_H_
  2985. #include "common.h"
  2986. #endif
  2987.  
  2988. #ifndef THREAD_H_
  2989. #include "thread.h"
  2990. #endif
  2991.  
  2992.  
  2993. #define MINPRIO 2
  2994.  
  2995.  
  2996. class GNU_Thread : public Thread
  2997. {
  2998. public:
  2999.     virtual void Suspend ();                // Suspend an active thread
  3000.     virtual void Resume ();                 // Resume a suspended thread
  3001.  
  3002.     virtual void Body () = 0;               // Body of "active" object (defined in the deriving class)
  3003.     virtual long Current_Thread () const;   // Returns current thread id
  3004.  
  3005.     // Initialize must be called exactly once at the start of the program
  3006.     static void Initialize ();
  3007.  
  3008. protected:
  3009.     static const int MaxPriority; // Maximum priority of a thread
  3010.     static long base_key;
  3011.  
  3012.     GNU_Thread (int priority = MaxPriority); // Create thread with given (or maximum) priority
  3013.     virtual ~GNU_Thread ();
  3014.  
  3015. private:
  3016.     static void Execute (int, char**, GNU_Thread*); // This routine calls the 'main' object code
  3017.     static boolean DoWait;
  3018.     static boolean SuspendMain;
  3019.     static int count;
  3020.  
  3021.     long thread_key;
  3022.     struct sem* to_wait;
  3023.     struct pcb* my_block;
  3024. };
  3025.  
  3026. #endif
  3027.     }
  3028.  
  3029.     if ((thread_key == 1) && (Self()->Current_Thread() == 0))
  3030.     {
  3031.     if (DoWait)
  3032.     {
  3033.         DoWait = false;
  3034.         waits(to_wait);
  3035.     }
  3036.     }    
  3037.     else
  3038.     waits(to_wait);
  3039. }
  3040.  
  3041. void GNU_Thread::Resume ()
  3042. {
  3043.     if ((thread_key == 1) && (Self()->Current_Thread() == 0))
  3044.     {
  3045.     readyp(my_block);
  3046. C++SIM/lwp_thread.cc
  3047.  * Copyright (C) 1993
  3048.  *
  3049.  * Department of Computing Science,
  3050.  * The University,
  3051.  * Newcastle upon Tyne,
  3052.  * UK.
  3053.  */
  3054.  
  3055. #ifndef COMMON_H_
  3056. #include "common.h"
  3057. #endif
  3058.  
  3059. #ifndef LWPTHREAD_H_
  3060. #include "lwp_thread.h"
  3061. #endif
  3062.  
  3063.  
  3064. /* These are the Sun C routines which give access to threads. They have to be
  3065.  * defined in this way. The multiple definitions for lwp_create are as a result
  3066.  * of the way in which C++ allows C routines to be declared and the way in which
  3067.  * Sun's lwp_create is defined.
  3068.  */
  3069.  
  3070. extern "C"
  3071. {
  3072. #include <lwp/stackdep.h>
  3073.  
  3074.     int pod_setmaxpri(int);
  3075.     int lwp_setstkcache(int, int);
  3076. #ifndef Scheduler_
  3077. #ifdef Main_
  3078.     int lwp_create(thread_t*, void (*func)(), int, int, stkalign_t*, int);
  3079. #else
  3080.     int lwp_create(thread_t*, void (*func)(LWP_Thread *), int, int, stkalign_t*, int, caddr_t);
  3081. #endif
  3082. #endif
  3083.     int lwp_yield(thread_t);
  3084.     int lwp_suspend(thread_t);
  3085.     int lwp_resume(thread_t);
  3086.     int lwp_setpri(thread_t, int);
  3087.     int lwp_self(thread_t*);
  3088.     int lwp_ping(thread_t);
  3089.     int lwp_sleep(struct timeval);
  3090. }
  3091.  
  3092. //
  3093. // Class LWP_Thread
  3094. //
  3095.  
  3096.  
  3097. const int LWP_Thread::MaxPriority=10;
  3098.  
  3099. #ifdef __GNUG__
  3100. thread_t* LWP_Thread::firstThread = 0;
  3101. boolean LWP_Thread::done = false;
  3102. #endif
  3103.  
  3104.  
  3105. LWP_Thread::LWP_Thread (int prio)
  3106. {
  3107.     caddr_t p1;
  3108.  
  3109.     p1 = (caddr_t) this;
  3110.     (void) lwp_create(&mid, LWP_Thread::Execute, prio, 0, lwp_newstk(), 1, p1);
  3111.     thread_key = mid.thread_key;
  3112.     (void) lwp_suspend(mid);
  3113. }
  3114.  
  3115. // For creating the LWP_Thread for "main"
  3116.  
  3117. LWP_Thread::LWP_Thread (thread_t tid)
  3118. {
  3119.     thread_key = tid.thread_key;
  3120. }
  3121.  
  3122. LWP_Thread::~LWP_Thread () {}
  3123.  
  3124. long LWP_Thread::Current_Thread () const
  3125. {
  3126.     thread_t tid;
  3127.  
  3128.     (void) lwp_self(&tid);
  3129.  
  3130.     return tid.thread_key;
  3131. }
  3132.  
  3133. void LWP_Thread::Execute (LWP_Thread *p1)
  3134. {
  3135. #ifdef __GNUG__
  3136.     if ((LWP_Thread::firstThread == 0) && (!done))
  3137.     {
  3138.     LWP_Thread::firstThread = new thread_t;
  3139.     (void) lwp_self(LWP_Thread::firstThread);
  3140.     lwp_suspend(*LWP_Thread::firstThread);
  3141.     }
  3142. #endif
  3143.     
  3144.     p1->Body();
  3145. }
  3146.  
  3147. void LWP_Thread::Suspend ()
  3148. {
  3149. #ifdef __GNUG__
  3150.     if ((LWP_Thread::firstThread != 0) && (!done))
  3151.     {
  3152.     done = true;
  3153.     lwp_resume(*LWP_Thread::firstThread);
  3154.     }
  3155. #endif
  3156.  
  3157.     (void) lwp_suspend(mid);    
  3158. }
  3159.  
  3160. void LWP_Thread::Resume ()
  3161. {
  3162. #ifdef __GNUG__
  3163.     if ((LWP_Thread::firstThread != 0) && (done))
  3164. #endif
  3165.     (void) lwp_resume(mid);
  3166. }
  3167.  
  3168. void LWP_Thread::Sleep (struct timeval doze) { (void) lwp_sleep(doze); }
  3169.  
  3170. thread_t LWP_Thread::Thread_ID () const { return mid; }
  3171.  
  3172.  
  3173.  
  3174. //
  3175. // Getting the main thread into the thread list...
  3176. //
  3177.  
  3178. class LWP_Main_Thread : public LWP_Thread
  3179. {
  3180. public:
  3181.     LWP_Main_Thread (thread_t t) : LWP_Thread(t) {}
  3182.     ~LWP_Main_Thread ();
  3183.  
  3184.     void Body ();
  3185. };
  3186.  
  3187. LWP_Main_Thread::~LWP_Main_Thread () {}
  3188.  
  3189. void LWP_Main_Thread::Body () {}
  3190.  
  3191. void LWP_Thread::Initialize ()
  3192. {
  3193.     (void) pod_setmaxpri(MaxPriority);
  3194.     (void) lwp_setstkcache(4000, 40);
  3195.  
  3196.     thread_t me;
  3197.     lwp_self(&me);
  3198.     new LWP_Main_Thread(me);
  3199. }
  3200.  lwp_create are as a result
  3201.  * of the way in which C++ allows C routines to be declared and the way in which
  3202.  * Sun's lwp_create is defined.
  3203.  */
  3204.  
  3205. extern "C"
  3206. {
  3207. #incC++SIM/lwp_thread.h
  3208.  * Copyright (C) 1993
  3209.  *
  3210.  * Department of Computing Science,
  3211.  * The University,
  3212.  * Newcastle upon Tyne,
  3213.  * UK.
  3214.  */
  3215.  
  3216. #ifndef LWP_THREAD_H_
  3217. #define LWP_THREAD_H_
  3218.  
  3219. #include <lwp/lwp.h>
  3220.  
  3221. #ifndef THREAD_H_
  3222. #include "thread.h"
  3223. #endif
  3224.  
  3225. /* This is the Sun thread implementation of the Thread virtual class. It provides
  3226.  * an implementation for all of the pure virtual functions declared in the Thread
  3227.  * base class.
  3228.  * The Initialize function must be called at the start of any program which uses the
  3229.  * threads implementation as it calls necessary Sun thread initialization routines.
  3230.  *
  3231.  * Note: if any problems occur when using the Sun thread package, try increasing the
  3232.  * stack size and/or the number of stacks to create in Initialize.
  3233.  */
  3234.  
  3235.  
  3236. class LWP_Thread : public Thread
  3237. {
  3238. public:
  3239.     virtual void Suspend ();                // Suspend an active thread
  3240.     virtual void Resume ();                 // Resume a suspended thread
  3241.     virtual void Sleep (struct timeval);    // Put active thread to sleep for duration specified
  3242.  
  3243.     virtual void Body () = 0;               // Body of "active" object (defined in the deriving class)
  3244.     virtual long Current_Thread () const;   // Returns current thread id
  3245.  
  3246.     thread_t Thread_ID () const;            // Returns current thread's Sun thread_key
  3247.  
  3248.     // Initialize must be called exactly once at the start of the program
  3249.     static void Initialize ();
  3250.  
  3251. protected:
  3252.     static const int MaxPriority;           // Maximum priority of a thread
  3253.  
  3254.     LWP_Thread (int priority = MaxPriority); // Create thread with given (or maximum) priority
  3255.     LWP_Thread (thread_t);                  // Create thread with given Sun thread_key
  3256.     virtual ~LWP_Thread ();
  3257.  
  3258. private:
  3259.     static void Execute (LWP_Thread*);     // This routine calls the 'main' object code
  3260.  
  3261. #ifdef __GNUG__
  3262.     static thread_t* firstThread;
  3263.     static boolean done;
  3264. #endif
  3265.  
  3266.     thread_t mid;
  3267. };
  3268.  
  3269. #endif
  3270. spend(*LWP_Thread::firstThread);
  3271.     }
  3272. #endif
  3273.     
  3274.     p1->Body();
  3275. }
  3276.  
  3277. void LWP_Thread::Suspend ()
  3278. {
  3279. #ifdef __GNUG__
  3280.     if ((LWP_Thread::firsC++SIM/thread.cc
  3281.  * Copyright (C) 1993
  3282.  *
  3283.  * Department of Computing Science,
  3284.  * The University,
  3285.  * Newcastle upon Tyne,
  3286.  * UK.
  3287.  */
  3288.  
  3289. #ifndef THREAD_H_
  3290. #include "thread.h"
  3291. #endif
  3292.  
  3293.  
  3294. class Thread *Thread::head = 0; // Initialise head of Thread list
  3295.  
  3296.  
  3297. Thread::Thread ()
  3298. {
  3299.     Thread *marker = head;
  3300.  
  3301.     if (head != 0)
  3302.     {
  3303.     while (marker->next != 0)
  3304.         marker = marker->next;
  3305.  
  3306.     marker->next = this;
  3307.     marker->next->prev = marker;
  3308.     marker = marker->next;
  3309.     marker->next = 0;
  3310.     }
  3311.     else
  3312.     {
  3313.     this->prev = 0;
  3314.     this->next = 0;
  3315.     head = this;
  3316.     }
  3317.  
  3318.     thread_key = 0;
  3319.     // Actual thread key value MUST be set in derived class constructor
  3320. }
  3321.  
  3322. Thread::~Thread ()
  3323. {
  3324.     if (this->prev != 0)
  3325.     this->prev->next = this->next;
  3326.     else
  3327.     head = this->next;
  3328. }
  3329.  
  3330. long Thread::Identity () const { return thread_key; }
  3331.  
  3332. Thread *Thread::Self ()
  3333. {
  3334.     if (!head) return 0;
  3335.  
  3336.     // Use any thread object (e.g., head) to get access to the current thread
  3337.     long my_id = head->Current_Thread();
  3338.  
  3339.     for (Thread *marker = head; marker; marker=marker->next)
  3340.     if (marker->thread_key == my_id)
  3341.         break;
  3342.  
  3343.     return marker;
  3344. }
  3345. ct (defined in the deriving class)
  3346.     virtual long Current_Thread () const;   // Returns current thread id
  3347.  
  3348.     thread_t Thread_ID () const;            // Returns current thread's Sun thread_key
  3349.  
  3350.     // Initialize must be called exactly once at the start of the program
  3351.     static void Initialize ();
  3352.  
  3353. protected:
  3354.     static const int MaxPriority;           // Maximum priority of a thread
  3355.  
  3356.     LWP_Thread (int priority = MaxPriority); // CrC++SIM/thread.h
  3357.  * Copyright (C) 1993
  3358.  *
  3359.  * Department of Computing Science,
  3360.  * The University,
  3361.  * Newcastle upon Tyne,
  3362.  * UK.
  3363.  */
  3364.  
  3365. #ifndef THREAD_H_
  3366. #define THREAD_H_
  3367.  
  3368. /* This class defines a template for threads packages which will be used to
  3369.  * provide "active" objects in C++. Such objects are not derived from this
  3370.  * class, but instead a thread implementation class is derived from this.
  3371.  * That class will then define the pure virtual functions, and "active" objects
  3372.  * are then derived from that class.
  3373.  * Because not every thread package provides an easy way of identifying and locating
  3374.  * threads, the Thread class does provide such a scheme through the use of the
  3375.  * Identify and Self operations. A linked list of threads is formed and added to
  3376.  * whenever a new thread is created.
  3377.  */
  3378.  
  3379. class Thread
  3380. {
  3381. public:
  3382.     virtual void Suspend () = 0; // How to suspend a thread
  3383.     virtual void Resume () = 0; // How to resume a suspended thread
  3384.     virtual void Body () = 0; // The 'main' part of the code
  3385.  
  3386.     virtual long Current_Thread () const = 0; // Should return some unique thread identity key
  3387.  
  3388.     virtual long Identity () const; // Returns the identify of this thread
  3389.     static Thread *Self (); // Returns the current thread
  3390.  
  3391. protected:
  3392.     Thread ();
  3393.     virtual ~Thread ();
  3394.  
  3395.     long thread_key;
  3396.  
  3397. private:
  3398.     Thread *next, *prev;
  3399.     static Thread *head;
  3400. };
  3401.  
  3402. #endif
  3403. tatic void Initialize ();
  3404.  
  3405. protected:
  3406.     static const int MaxPriority;           // Maximum priority of a thread
  3407.  
  3408.     LWP_Thread (int priority = MaxPriority); // CrC++SIM/Process.n
  3409.  * Copyright (C) 1993
  3410.  *
  3411.  * Department of Computing Science,
  3412.  * The University,
  3413.  * Newcastle upon Tyne,
  3414.  * UK.
  3415.  */
  3416.  
  3417.  
  3418. #if defined(NO_INLINES) && !defined(PROCESS_CC_)
  3419.  
  3420. #else
  3421.  
  3422. #ifndef NO_INLINES
  3423. #  define INLINEF inline
  3424. #else
  3425. #  define INLINEF
  3426. #endif
  3427.  
  3428.  
  3429. INLINEF void Process::set_evtime (double time)
  3430. {
  3431.     wakeuptime = time;
  3432. }
  3433.  
  3434. INLINEF void Process::Activate ()
  3435. {
  3436.     ReActivate();
  3437. }
  3438.  
  3439. INLINEF double  Process::evtime () const
  3440. {
  3441.     return wakeuptime;
  3442. }
  3443.  
  3444. INLINEF boolean Process::terminated () const
  3445. {
  3446.     return Terminated;
  3447. }
  3448.  
  3449.  
  3450. #ifdef INLINEF
  3451. #  undef INLINEF
  3452. #endif
  3453.  
  3454. #endif
  3455.  * The University,
  3456.  * Newcastle upon Tyne,
  3457.  * UK.
  3458.  */
  3459.  
  3460.  
  3461. #if defined(NO_INLINES) && !defined(PROCESS_CC_)
  3462.  
  3463. #else
  3464.  
  3465. #ifndef NO_INLINES
  3466. #  define INLINEF inline
  3467. #else
  3468. #  define INLINEF
  3469. #endif
  3470.  
  3471.  
  3472. INLINEF void Process::set_evtime (double time)
  3473. {
  3474.     wakeuptime = time;
  3475. }
  3476.  
  3477. INLINEF void Process::Activate ()
  3478. {
  3479.     ReActivate();
  3480. }
  3481.  
  3482. INLINEF double  Process::evtime () const
  3483. {
  3484.     return wakeuptime;
  3485. }
  3486.  
  3487. INLINEF boolean Process::terminated () const
  3488. {
  3489.     returnC++SIM/Process.cc
  3490.  * Copyright (C) 1993
  3491.  *
  3492.  * Department of Computing Science,
  3493.  * The University,
  3494.  * Newcastle upon Tyne,
  3495.  * UK.
  3496.  */
  3497.  
  3498. #include <iostream.h>
  3499. #include <stdlib.h>
  3500.  
  3501. #ifndef COMMON_H_
  3502. #include "common.h"
  3503. #endif
  3504.  
  3505. #ifndef PROCESS_H_
  3506. #include "Process.h"
  3507. #endif
  3508.  
  3509. #ifndef PROCESSITERATOR_H_
  3510. #include "ProcessIterator.h"
  3511. #endif
  3512.  
  3513. #ifndef PROCESSLIST_H_
  3514. #include "ProcessList.h"
  3515. #endif
  3516.  
  3517. #ifndef PROCESSCONS_H_
  3518. #include "ProcessCons.h"
  3519. #endif
  3520.  
  3521. static ProcessList ReadyQueue;
  3522. static Process *Current = 0;
  3523.  
  3524. //
  3525. // create scheduler task at MINPRIO
  3526. //
  3527.  
  3528. Scheduler::Scheduler () : Thread_Type(MINPRIO) {}
  3529.  
  3530. Scheduler::~Scheduler () {}
  3531.  
  3532. void Scheduler::Body ()
  3533. {
  3534.     for (;;)
  3535.     {
  3536.     Current = ReadyQueue.Remove();
  3537.     if (Current == 0)    // all done
  3538.     {
  3539. #ifdef DEBUG
  3540.         cerr << "Scheduler queue is empty.\n";
  3541. #endif
  3542.         exit(0);
  3543.     }
  3544.  
  3545.     if (Current->evtime() < 0)
  3546.         cerr << "Scheduler Error: Process WakeupTime Invalid.\n";
  3547.     else
  3548.         SimulatedTime = Current->evtime();
  3549.  
  3550. #ifdef DEBUG
  3551.     cerr << "Simulated time is now " << SimulatedTime << "\n";
  3552. #endif
  3553.  
  3554.     Current->Resume();
  3555.     }
  3556. }
  3557.  
  3558. double Scheduler::CurrentTime () const { return SimulatedTime; }
  3559.  
  3560.  
  3561. //
  3562. // Class Process
  3563. //
  3564.  
  3565. const int Process::Never=-1; // Process will never awaken.
  3566.  
  3567. Process::~Process () {}
  3568.  
  3569. double Process::CurrentTime () { return SimulatedTime; }
  3570.  
  3571.  
  3572. double Process::Time () const { return SimulatedTime; }
  3573.  
  3574. void Process::ActivateBefore (Process &p)
  3575. {
  3576.     // No op if already scheduled
  3577.     if (idle()) return;
  3578.  
  3579.     if (ReadyQueue.InsertBefore(*this, p))
  3580.     wakeuptime = p.wakeuptime;
  3581.     else
  3582.     cerr << "ActivateBefore failed because 'before' process is not scheduled" << endl;
  3583. }
  3584.  
  3585. void Process::ActivateAfter (Process &p)
  3586. {
  3587.     // No op if already scheduled
  3588.     if (idle()) return;
  3589.  
  3590.     if (ReadyQueue.InsertAfter(*this, p))
  3591.     wakeuptime = p.wakeuptime;
  3592.     else
  3593.     cerr << "ActivateAfter failed because 'after' process is not scheduled" << endl;
  3594. }
  3595.  
  3596. void Process::ActivateAt (double AtTime, boolean prior)
  3597. {
  3598.     // No op if already scheduled
  3599.     if (idle()) return;
  3600.  
  3601.     wakeuptime = AtTime;
  3602.     ReadyQueue.Insert(*this, prior);
  3603. }
  3604.  
  3605. void Process::ActivateDelay (double Delay, boolean prior)
  3606. {
  3607.     // No op if already scheduled
  3608.     if (idle()) return;
  3609.  
  3610.     wakeuptime = SimulatedTime + Delay;
  3611.     ReadyQueue.Insert(*this, prior);
  3612. }
  3613.  
  3614.  
  3615. // Similarly, there are four ways to reactivate
  3616. // Note that if a process is already scheduled, the reactivate
  3617. // will simply re-schedule the process.
  3618.  
  3619. void Process::ReActivateBefore (Process &p)
  3620. {
  3621.     Cancel();
  3622.     ActivateBefore(p);
  3623. }
  3624.  
  3625. void Process::ReActivateAfter  (Process &p)
  3626. {
  3627.     Cancel();
  3628.     ActivateAfter(p);
  3629. }
  3630.  
  3631. void Process::ReActivateAt (double AtTime, boolean prior)
  3632. {
  3633.     Cancel();
  3634.     ActivateAt(AtTime, prior);
  3635. }
  3636.  
  3637. void Process::ReActivateDelay (double Delay, boolean prior)
  3638. {
  3639.     Cancel();
  3640.     ActivateDelay(Delay, prior);
  3641. }
  3642.  
  3643. void Process::ReActivate ()
  3644. {
  3645.     if (idle())
  3646.     ReadyQueue.Remove(this);
  3647.     set_evtime(CurrentTime());
  3648.     Resume();
  3649. }
  3650.  
  3651. // cancels next burst of activity, process becomes idle
  3652. void Process::Cancel ()
  3653. {
  3654.     if (idle())
  3655.     ReadyQueue.Remove(this);
  3656.     else
  3657.     Suspend();
  3658.  
  3659.     wakeuptime = Process::Never;
  3660. }
  3661.  
  3662. boolean Process::idle ()
  3663. {
  3664.     if (wakeuptime == CurrentTime())
  3665.     return false;
  3666.     else
  3667.     return true;
  3668. }
  3669.  
  3670. Process::Process() : Thread_Type()
  3671. {
  3672.     wakeuptime = CurrentTime();
  3673. }
  3674.  
  3675. // suspend current process for simulated time t
  3676. void Process::Hold (double t) 
  3677. {
  3678.     ActivateDelay(t);
  3679.     Suspend();
  3680. }
  3681.  
  3682. // suspend current process indefinitely (i.e., make idle)
  3683. void Process::Passivate ()
  3684. {
  3685.     wakeuptime = Process::Never;
  3686.     this->Terminated = true;
  3687.     Suspend();
  3688. }
  3689.  
  3690.  
  3691. #ifdef NO_INLINES
  3692. #  define PROCESS_CC_
  3693. #  include "Process.n"
  3694. #  undef PROCESS_CC_
  3695. #endif
  3696. private:
  3697.     double Mean,StandardDeviation;
  3698.     double p;
  3699. };
  3700.  
  3701. class NormalStream : public RandomStream
  3702. {
  3703. public:
  3704.     NormalStream (double Mean, double StandardDeviation, int StreamSelect=0);
  3705.     virtual double operator() ();
  3706.  
  3707. private:
  3708.     double Mean,StandardDeviation;
  3709.     double z;
  3710. };
  3711.  
  3712. #endif // RANDOM_H
  3713.  
  3714. lgorithms, Knuth, Addison-Wesley, p.117
  3715.  
  3716.     double X2;
  3717.  
  3718.     if (z!=0.0) {
  3719.     X2 = z;
  3720.     z = 0.0;
  3721.     } else {
  3722.     double SC++SIM/Version
  3723.  * Copyright (C) 1993
  3724.  *
  3725.  * Department of Computing Science,
  3726.  * The University,
  3727.  * Newcastle upon Tyne,
  3728.  * UK.
  3729.  */
  3730.  
  3731. This is version 1.1 of C++SIM. The only changes from 1.0 are bug fixes in
  3732. the code and enhancements to allow it to work with g++ and Sun's lwp
  3733. package at the same time (up until now if you wanted to use g++ you had to
  3734. use their threads package too).
  3735.  
  3736. Mark Little 16/7/93.
  3737. CONS_H_
  3738. #include "ProcessCons.h"
  3739. #endif
  3740.  
  3741. static ProcessList ReadyQueue;
  3742. static Process *Current = 0;
  3743.  
  3744. //
  3745. // create schedu
  3746.  * Copyright (C) 1993
  3747.  *
  3748.  * Department of Computing Science,
  3749.  * The University,
  3750.  * Newcastle upon Tyne,
  3751.  * UK.
  3752.  */
  3753.  
  3754.  
  3755. #if defined(NO_INLINES) && !defined(PROCESS_CC_)
  3756.  
  3757. #else
  3758.  
  3759. #ifndef NO_INLINES
  3760. #  define INLINEF inline
  3761. #else
  3762. #  define INLINEF
  3763. #endif
  3764.  
  3765.  
  3766. INLINEF void Process::set_evtime (double time)
  3767. {
  3768.     wakeuptime = time;
  3769. }
  3770.  
  3771. INLINEF void Process::Activate ()
  3772. {
  3773.     ReActivate();
  3774. }
  3775.  
  3776. INLINEF double  Process::evtime () const
  3777. {
  3778.     return wakeuptime;
  3779. }
  3780.  
  3781. INLINEF boolean Process::terminated () const
  3782. {
  3783.     return
  3784. }
  3785.